diff options
author | Emmanuel Gil Peyrot <emmanuel.peyrot@collabora.com> | 2016-02-09 09:27:46 +0000 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2016-02-09 19:04:22 +0000 |
commit | 49f55eabda703e9b651f3ca549193b89c2a5b0fd (patch) | |
tree | abbee908e2a6d2d30d87e3d089bba0f296d7400c /slideshow | |
parent | 8e0ed97101356ba537d0f85b2971bc22eabc633b (diff) |
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.
also:
slideshow: Only retrieve each uniform location once
Change-Id: I8aaa1428c4481661283bf69b5e56aa4d95fb80dd
Reviewed-on: https://gerrit.libreoffice.org/22232
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/22245
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'slideshow')
-rw-r--r-- | slideshow/Package_opengl.mk | 1 | ||||
-rw-r--r-- | slideshow/opengl/vortexFragmentShader.glsl | 34 | ||||
-rw-r--r-- | slideshow/opengl/vortexGeometryShader.glsl | 32 | ||||
-rwxr-xr-x | slideshow/opengl/vortexVertexShader.glsl | 19 | ||||
-rw-r--r-- | slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx | 160 | ||||
-rw-r--r-- | slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx | 4 |
6 files changed, 214 insertions, 36 deletions
diff --git a/slideshow/Package_opengl.mk b/slideshow/Package_opengl.mk index 2781cd78ba3f..eef06e968951 100644 --- a/slideshow/Package_opengl.mk +++ b/slideshow/Package_opengl.mk @@ -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 \ )) diff --git a/slideshow/opengl/vortexFragmentShader.glsl b/slideshow/opengl/vortexFragmentShader.glsl new file mode 100644 index 000000000000..3212ebef7661 --- /dev/null +++ b/slideshow/opengl/vortexFragmentShader.glsl @@ -0,0 +1,34 @@ +/* -*- 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: */ diff --git a/slideshow/opengl/vortexGeometryShader.glsl b/slideshow/opengl/vortexGeometryShader.glsl index 46999efad55f..312babac1c2f 100644 --- a/slideshow/opengl/vortexGeometryShader.glsl +++ b/slideshow/opengl/vortexGeometryShader.glsl @@ -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(); } diff --git a/slideshow/opengl/vortexVertexShader.glsl b/slideshow/opengl/vortexVertexShader.glsl index 603c62960f2a..9bab2d9e0397 100755 --- a/slideshow/opengl/vortexVertexShader.glsl +++ b/slideshow/opengl/vortexVertexShader.glsl @@ -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; diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx index cf310c6f5ddc..25b307a0a045 100644 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx +++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx @@ -32,6 +32,7 @@ #include <vcl/opengl/OpenGLHelper.hxx> #include <algorithm> +#include <array> #include <utility> #include <comphelper/random.hxx> @@ -169,6 +170,7 @@ bool OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" ); m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" ); m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" ); + m_nTimeLocation = glGetUniformLocation( m_nProgramObject, "time" ); glGenVertexArrays(1, &m_nVertexArrayObject); glBindVertexArray(m_nVertexArrayObject); @@ -250,9 +252,7 @@ void OGLTransitionImpl::displaySlides_( double nTime, sal_Int32 glLeavingSlideTe CHECK_GL_ERROR(); applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); - GLint location = glGetUniformLocation( m_nProgramObject, "time" ); - if( location != -1 ) - glUniform1f( location, nTime ); + glUniform1f( m_nTimeLocation, nTime ); glActiveTexture( GL_TEXTURE2 ); glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex ); @@ -1547,24 +1547,28 @@ class VortexTransition : public PermTextureTransition public: VortexTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, int nNX, int nNY) : PermTextureTransition(rScene, rSettings) - , mnTileInfoLocation(0) - , mnTileInfoBuffer(0) , 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 mnTileInfoLocation; - GLuint mnTileInfoBuffer; + 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; @@ -1584,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 ) @@ -1595,10 +1629,16 @@ void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); CHECK_GL_ERROR(); + mnSlideLocation = glGetUniformLocation(m_nProgramObject, "slide"); 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)); @@ -1634,24 +1674,92 @@ 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 ) { CHECK_GL_ERROR(); applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); + glUniform1f( m_nTimeLocation, nTime ); + glUniform1f( mnShadowLocation, 1.0 ); - GLint location = glGetUniformLocation( m_nProgramObject, "time" ); - if( location != -1 ) - glUniform1f( location, nTime ); + std::array<GLint, 4> viewport; + glGetIntegerv(GL_VIEWPORT, viewport.data()); + glViewport(0, 0, 2048, 2048); - location = glGetUniformLocation( m_nProgramObject, "slide" ); + 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 ); - if( location != -1 ) - glUniform1f( location, 0.0 ); + 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 ); - if( location != -1 ) - glUniform1f( location, 1.0 ); + glUniform1f( mnSlideLocation, 1.0 ); displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); CHECK_GL_ERROR(); } @@ -1672,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++) @@ -1910,9 +2018,8 @@ private: 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 maHexagonSizeLocation = 0; - GLint maTimeLocation = 0; - GLint maSelectedTextureLocation = 0; + GLint maHexagonSizeLocation = -1; + GLint maSelectedTextureLocation = -1; }; GLuint HoneycombTransition::makeShader() const @@ -1927,7 +2034,6 @@ void HoneycombTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_In CHECK_GL_ERROR(); maHexagonSizeLocation = glGetUniformLocation(m_nProgramObject, "hexagonSize"); - maTimeLocation = glGetUniformLocation( m_nProgramObject, "time" ); maSelectedTextureLocation = glGetUniformLocation( m_nProgramObject, "selectedTexture" ); CHECK_GL_ERROR(); @@ -1942,7 +2048,7 @@ void HoneycombTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlide { CHECK_GL_ERROR(); applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); - glUniform1f( maTimeLocation, nTime ); + glUniform1f( m_nTimeLocation, nTime ); // The back (entering) slide needs to be drawn before the front (leaving) one in order for blending to work. diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx index d8cbbfeeb102..449a72fc81f5 100644 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx +++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx @@ -240,6 +240,10 @@ protected: /** VBO in which to put primitive data */ GLuint m_nVertexBufferObject = 0u; + + /** Location of the "time" uniform + */ + GLint m_nTimeLocation = -1; }; |