Kaydet (Commit) 0c14c7ba authored tarafından Emmanuel Gil Peyrot's avatar Emmanuel Gil Peyrot Kaydeden (comit) Michael Meeks

slideshow: Add shadows to the Vortex transition

These are done using a shadow mapping technique, we render both slides
from the point of view of the light, and then do a second pass in which
we lower the light of the fragment if some other cube is above it.

Change-Id: I8aaa1428c4481661283bf69b5e56aa4d95fb80dd
Reviewed-on: https://gerrit.libreoffice.org/22232Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMichael Meeks <michael.meeks@collabora.com>
üst 882d27fc
......@@ -25,6 +25,7 @@ $(eval $(call gb_Package_add_files,slideshow_opengl_shader,$(LIBO_ETC_FOLDER)/op
staticFragmentShader.glsl \
vortexVertexShader.glsl \
vortexGeometryShader.glsl \
vortexFragmentShader.glsl \
rippleFragmentShader.glsl \
))
......
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#version 150
uniform sampler2D slideTexture;
uniform sampler2D leavingShadowTexture;
uniform sampler2D enteringShadowTexture;
in vec2 v_texturePosition;
in vec3 v_normal;
in vec4 shadowCoordinate;
void main() {
vec3 lightVector = vec3(0.0, 0.0, 1.0);
float light = max(dot(lightVector, v_normal), 0.0);
vec4 fragment = texture2D(slideTexture, v_texturePosition);
float visibility = 1.0;
const float epsilon = 0.0001;
if (texture2D(leavingShadowTexture, shadowCoordinate.xy).r < shadowCoordinate.z - epsilon)
visibility *= 0.7;
if (texture2D(enteringShadowTexture, shadowCoordinate.xy).r < shadowCoordinate.z - epsilon)
visibility *= 0.7;
vec4 black = vec4(0.0, 0.0, 0.0, fragment.a);
gl_FragColor = mix(black, fragment, visibility * light);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -14,16 +14,41 @@ layout(triangle_strip, max_vertices=11) out;
in vec2 g_texturePosition[];
in vec3 g_normal[];
in mat4 projectionMatrix[];
in mat4 modelViewMatrix[];
in mat4 shadowMatrix[];
in mat4 transform[];
in float nTime[];
in float startTime[];
in float endTime[];
uniform mat4 u_projectionMatrix;
out vec2 v_texturePosition;
out vec3 v_normal;
out vec4 shadowCoordinate;
mat4 identityMatrix(void)
{
return mat4(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
}
mat4 scaleMatrix(vec3 axis)
{
mat4 matrix = identityMatrix();
matrix[0][0] = axis.x;
matrix[1][1] = axis.y;
matrix[2][2] = axis.z;
return matrix;
}
mat4 translationMatrix(vec3 axis)
{
mat4 matrix = identityMatrix();
matrix[3] = vec4(axis, 1.0);
return matrix;
}
void emitHexagonVertex(int index, vec3 translation, float fdsq)
{
......@@ -37,7 +62,8 @@ void emitHexagonVertex(int index, vec3 translation, float fdsq)
v_normal = normalize(vec3(normalMatrix * transform[index] * vec4(g_normal[index], 0.0)));
v_normal.z *= fdsq;
gl_Position = u_projectionMatrix * modelViewMatrix[index] * pos;
gl_Position = projectionMatrix[index] * modelViewMatrix[index] * pos;
shadowCoordinate = translationMatrix(vec3(0.5, 0.5, 0.5)) * scaleMatrix(vec3(0.5, 0.5, 0.5)) * shadowMatrix[index] * modelViewMatrix[index] * pos;
v_texturePosition = g_texturePosition[index];
EmitVertex();
}
......
......@@ -16,6 +16,7 @@ in vec3 a_normal;
in vec2 a_texCoord;
in float tileInfo;
uniform mat4 u_projectionMatrix;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_sceneTransformMatrix;
uniform mat4 u_primitiveTransformMatrix;
......@@ -25,10 +26,15 @@ uniform float time;
uniform ivec2 numTiles;
uniform sampler2D permTexture;
uniform float slide;
uniform float shadow;
uniform mat4 orthoProjectionMatrix;
uniform mat4 orthoViewMatrix;
out vec2 g_texturePosition;
out vec3 g_normal;
out mat4 projectionMatrix;
out mat4 modelViewMatrix;
out mat4 shadowMatrix;
out mat4 transform;
out float nTime;
out float startTime;
......@@ -134,13 +140,14 @@ void main( void )
* rotationMatrix(vec3(0.0, 1.0, 0.0), clamp(rotation, -1.0, 1.0) * M_PI)
* translationMatrix(-translationVector)
* transform;
}
// Add a translation movement to the leaving slide so it doesn’t exactly mirror the entering one.
if (isLeavingSlide && nTime > 0.3)
{
float movement = smoothstep(0.0, 1.0, (nTime - 0.3) * 2.0);
transform = translationMatrix(vec3(-movement, 0.0, -0.5 * movement)) * transform;
}
if (shadow < 0.5) {
projectionMatrix = u_projectionMatrix;
shadowMatrix = orthoProjectionMatrix * orthoViewMatrix;
} else {
projectionMatrix = orthoProjectionMatrix * orthoViewMatrix;
shadowMatrix = mat4(0.0);
}
modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
......
......@@ -32,6 +32,7 @@
#include <vcl/opengl/OpenGLHelper.hxx>
#include <algorithm>
#include <array>
#include <utility>
#include <comphelper/random.hxx>
......@@ -1549,20 +1550,25 @@ public:
, maNumTiles(nNX,nNY)
{
mvTileInfo.resize(6*maNumTiles.x*maNumTiles.y);
mnFramebuffers[0] = 0;
mnFramebuffers[1] = 0;
mnDepthTextures[0] = 0;
mnDepthTextures[1] = 0;
}
private:
virtual void prepare( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) override;
virtual void finishTransition() override;
virtual GLuint makeShader() const override;
virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) override;
virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) override;
GLint mnSlideLocation = -1;
GLint mnTileInfoLocation = -1;
GLuint mnTileInfoBuffer = 0u;
GLint mnShadowLocation = -1;
std::array<GLuint, 2> mnFramebuffers;
std::array<GLuint, 2> mnDepthTextures;
glm::ivec2 maNumTiles;
......@@ -1582,9 +1588,39 @@ void VortexTransition::prepare( double, double, double, double, double )
CHECK_GL_ERROR();
}
void VortexTransition::finishTransition()
{
PermTextureTransition::finishTransition();
CHECK_GL_ERROR();
glDeleteTextures(2, mnDepthTextures.data());
mnDepthTextures = {0u, 0u};
CHECK_GL_ERROR();
glDeleteFramebuffers(2, mnFramebuffers.data());
mnFramebuffers = {0u, 0u};
glDeleteBuffers(1, &mnTileInfoBuffer);
mnTileInfoBuffer = 0u;
mnSlideLocation = -1;
mnTileInfoLocation = -1;
mnShadowLocation = -1;
CHECK_GL_ERROR();
}
GLuint VortexTransition::makeShader() const
{
return OpenGLHelper::LoadShaders( "vortexVertexShader", "basicFragmentShader", "vortexGeometryShader" );
return OpenGLHelper::LoadShaders( "vortexVertexShader", "vortexFragmentShader", "vortexGeometryShader" );
}
static glm::mat4 lookAt(glm::vec3 eye, glm::vec3 center, glm::vec3 up) {
glm::vec3 f = glm::normalize(center - eye);
glm::vec3 u = glm::normalize(up);
glm::vec3 s = glm::normalize(glm::cross(f, u));
u = glm::cross(s, f);
return glm::mat4(s.x, u.x, -f.x, 0,
s.y, u.y, -f.y, 0,
s.z, u.z, -f.z, 0,
-glm::dot(s, eye), -glm::dot(u, eye), glm::dot(f, eye), 1);
}
void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex )
......@@ -1594,12 +1630,15 @@ void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32
CHECK_GL_ERROR();
mnSlideLocation = glGetUniformLocation(m_nProgramObject, "slide");
CHECK_GL_ERROR();
mnTileInfoLocation = glGetAttribLocation(m_nProgramObject, "tileInfo");
CHECK_GL_ERROR();
GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles");
mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow");
GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix");
GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix");
GLint location = glGetUniformLocation(m_nProgramObject, "leavingShadowTexture");
glUniform1i(location, 2);
location = glGetUniformLocation(m_nProgramObject, "enteringShadowTexture");
glUniform1i(location, 3);
CHECK_GL_ERROR();
glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(maNumTiles));
......@@ -1635,6 +1674,63 @@ void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERROR();
double EyePos(10.0);
double RealF(1.0);
double RealN(-1.0);
double RealL(-2.0);
double RealR(2.0);
double RealB(-2.0);
double RealT(2.0);
double ClipN(EyePos+5.0*RealN);
double ClipF(EyePos+15.0*RealF);
double ClipL(RealL*8.0);
double ClipR(RealR*8.0);
double ClipB(RealB*8.0);
double ClipT(RealT*8.0);
glm::mat4 projection = glm::ortho<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
//This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
1.0);
projection = glm::scale(projection, scale);
glUniformMatrix4fv(nOrthoProjectionMatrix, 1, false, glm::value_ptr(projection));
glm::mat4 view = lookAt(glm::vec3(-1, 1, EyePos), glm::vec3(-0.5, 0.5, 0), glm::vec3(0, 1, 0));
glUniformMatrix4fv(nOrthoViewMatrix, 1, false, glm::value_ptr(view));
// Generate the framebuffers and textures for the shadows.
glGenTextures(2, mnDepthTextures.data());
glGenFramebuffers(2, mnFramebuffers.data());
for (int i : {0, 1}) {
glBindTexture(GL_TEXTURE_2D, mnDepthTextures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[i]);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mnDepthTextures[i], 0);
glDrawBuffer(GL_NONE); // No color buffer is drawn to.
// Always check that our framebuffer is ok
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
SAL_WARN("slideshow.opengl", "Wrong framebuffer!");
return;
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture( GL_TEXTURE2 );
glBindTexture( GL_TEXTURE_2D, mnDepthTextures[0] );
glActiveTexture( GL_TEXTURE3 );
glBindTexture( GL_TEXTURE_2D, mnDepthTextures[1] );
glActiveTexture( GL_TEXTURE0 );
}
void VortexTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale )
......@@ -1642,7 +1738,25 @@ void VortexTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex
CHECK_GL_ERROR();
applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
glUniform1f( m_nTimeLocation, nTime );
glUniform1f( mnShadowLocation, 1.0 );
std::array<GLint, 4> viewport;
glGetIntegerv(GL_VIEWPORT, viewport.data());
glViewport(0, 0, 2048, 2048);
glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[0]);
glClear(GL_DEPTH_BUFFER_BIT);
glUniform1f( mnSlideLocation, 0.0 );
displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[1]);
glClear(GL_DEPTH_BUFFER_BIT);
glUniform1f( mnSlideLocation, 1.0 );
displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUniform1f( mnShadowLocation, 0.0 );
glUniform1f( mnSlideLocation, 0.0 );
displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
glUniform1f( mnSlideLocation, 1.0 );
......@@ -1666,7 +1780,7 @@ makeVortexTransition(const Primitives_t& rLeavingSlidePrimitives,
std::shared_ptr<OGLTransitionImpl> makeVortex()
{
const int NX = 64, NY = 64;
const int NX = 96, NY = 96;
Primitive Slide;
for (int x = 0; x < NX; x++)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment