From 8600d3bc6104224c4efa7d214d2d5683ac44cc45 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Mon, 3 Mar 2014 00:47:13 +0100 Subject: [PATCH] IBL: Spheremap now reflects skybox --- data/shaders/objectpass_spheremap.frag | 22 +++++++++------------- src/graphics/irr_driver.hpp | 3 ++- src/graphics/shaders.cpp | 8 +++++++- src/graphics/shaders.hpp | 4 ++-- src/graphics/stkmesh.cpp | 20 ++++++++++++++++++-- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/data/shaders/objectpass_spheremap.frag b/data/shaders/objectpass_spheremap.frag index c3a4c086a..8a02ae7ab 100644 --- a/data/shaders/objectpass_spheremap.frag +++ b/data/shaders/objectpass_spheremap.frag @@ -1,4 +1,6 @@ -uniform sampler2D tex; +uniform samplerCube tex; +uniform mat4 invproj; +uniform vec2 screen; #if __VERSION__ >= 130 in vec3 nor; @@ -10,18 +12,12 @@ varying vec3 nor; void main() { - // Calculate the spherical UV - const vec3 forward = vec3(0.0, 0.0, 1.0); + vec3 fpos = gl_FragCoord.xyz / vec3(screen, 1.); + vec4 xpos = 2.0 * vec4(fpos, 1.0) - 1.0; + xpos = invproj * xpos; - // get the angle between the forward vector and the horizontal portion of the normal - vec3 normal_x = normalize(vec3(nor.x, 0.0, nor.z)); - float sin_theta_x = length(cross( forward, normal_x )) * nor.x / abs(nor.x); + xpos.xyz /= xpos.w; + vec4 detail0 = texture(tex, reflect(xpos.xyz, nor)); - // get the angle between the forward vector and the vertical portion of the normal - vec3 normal_y = normalize(vec3(0.0, nor.y, nor.z)); - float sin_theta_y = length(cross( forward, normal_y )) * nor.y / abs(nor.y); - - vec4 detail0 = texture(tex, 0.5 * vec2(sin_theta_x, sin_theta_y) + 0.5); - - FragColor = vec4(detail0.xyz, 1.); + FragColor = vec4(detail0.xyz, 1.); } diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index a6fe0a0b8..9155451bf 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -115,7 +115,7 @@ private: core::matrix4 m_ViewMatrix, m_InvViewMatrix, m_ProjMatrix, m_InvProjMatrix, m_ProjViewMatrix, m_InvProjViewMatrix; std::vector SkyboxTextures; - GLuint SkyboxCubeMap, ConvolutedSkyboxCubeMap; + float blueSHCoeff[9]; float greenSHCoeff[9]; float redSHCoeff[9]; @@ -130,6 +130,7 @@ private: RES_CHANGE_CANCEL} m_resolution_changing; public: + GLuint SkyboxCubeMap, ConvolutedSkyboxCubeMap; /** A simple class to store video resolutions. */ class VideoMode { diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 78ffea464..579c72b73 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -678,6 +678,8 @@ namespace MeshShader GLuint SphereMapShader::uniform_MVP; GLuint SphereMapShader::uniform_TIMV; GLuint SphereMapShader::uniform_tex; + GLuint SphereMapShader::uniform_invproj; + GLuint SphereMapShader::uniform_screen; void SphereMapShader::init() { @@ -687,12 +689,16 @@ namespace MeshShader uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix"); uniform_TIMV = glGetUniformLocation(Program, "TransposeInverseModelView"); uniform_tex = glGetUniformLocation(Program, "tex"); + uniform_invproj = glGetUniformLocation(Program, "invproj"); + uniform_screen = glGetUniformLocation(Program, "screen"); } - void SphereMapShader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, unsigned TU_tex) + void SphereMapShader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &InvProj, const core::vector2df& screen, unsigned TU_tex) { glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer()); glUniformMatrix4fv(uniform_TIMV, 1, GL_FALSE, TransposeInverseModelView.pointer()); + glUniformMatrix4fv(uniform_invproj, 1, GL_FALSE, InvProj.pointer()); + glUniform2f(uniform_screen, screen.X, screen.Y); glUniform1i(uniform_tex, TU_tex); } diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index c0d8869a3..84d28ab68 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -152,10 +152,10 @@ class SphereMapShader public: static GLuint Program; static GLuint attrib_position, attrib_normal; - static GLuint uniform_MVP, uniform_TIMV, uniform_tex; + static GLuint uniform_MVP, uniform_TIMV, uniform_tex, uniform_invproj, uniform_screen; static void init(); - static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, unsigned TU_tex); + static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &InvProj, const core::vector2df& screen, unsigned TU_tex); }; class SplattingShader diff --git a/src/graphics/stkmesh.cpp b/src/graphics/stkmesh.cpp index 944753676..6078bdb4d 100644 --- a/src/graphics/stkmesh.cpp +++ b/src/graphics/stkmesh.cpp @@ -226,13 +226,29 @@ void drawSphereMap(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionM GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; - setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + glActiveTexture(GL_TEXTURE0); + if (!irr_driver->SkyboxCubeMap) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ONE }; + glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + glBindBuffer(GL_TEXTURE_CUBE_MAP, irr_driver->SkyboxCubeMap); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } glUseProgram(MeshShader::SphereMapShader::Program); - MeshShader::SphereMapShader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, 0); + MeshShader::SphereMapShader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, irr_driver->getInvProjMatrix(), core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height), 0); glBindVertexArray(mesh.vao_second_pass); glDrawElements(ptype, count, itype, 0); + if (!irr_driver->SkyboxCubeMap) + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } } void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix)