diff --git a/data/shaders/rsm.frag b/data/shaders/rsm.frag new file mode 100644 index 000000000..8c1d0f077 --- /dev/null +++ b/data/shaders/rsm.frag @@ -0,0 +1,12 @@ +uniform sampler2D tex; + +in vec2 uv; +in vec3 nor; +layout (location = 0) out vec3 RSMColor; +layout (location = 1) out vec3 RSMNormals; + +void main() +{ + RSMColor = texture(tex, uv).xyz; + RSMNormals = .5 * normalize(nor) + .5; +} diff --git a/data/shaders/rsm.vert b/data/shaders/rsm.vert new file mode 100644 index 000000000..d5d08d48b --- /dev/null +++ b/data/shaders/rsm.vert @@ -0,0 +1,26 @@ +uniform mat4 ModelMatrix; +uniform mat4 InverseModelMatrix; +uniform mat4 RSMMatrix; + +uniform mat4 TextureMatrix = + mat4(1., 0., 0., 0., + 0., 1., 0., 0., + 0., 0., 1., 0., + 0., 0., 0., 1.); + + +in vec3 Position; +in vec2 Texcoord; +in vec3 Normal; +out vec3 nor; +out vec2 uv; + + +void main(void) +{ + mat4 ModelViewProjectionMatrix = RSMMatrix * ModelMatrix; + mat4 TransposeInverseModel = transpose(InverseModelMatrix); + gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.); + nor = (vec4(Normal, 0.)).xyz; + uv = (TextureMatrix * vec4(Texcoord, 1., 1.)).xy; +} diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index dff1932c0..d9652f857 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -203,6 +203,7 @@ private: /** RTTs. */ RTT *m_rtts; std::vector sun_ortho_matrix; + core::matrix4 rsm_matrix; /** Additional details to be shown in case that a texture is not found. * This is used to specify details like: "while loading kart '...'" */ diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index d80bb92b2..5c5e8c78c 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -195,6 +195,12 @@ void IrrDriver::renderGLSL(float dt) irr_driver->getFBO(FBO_NORMAL_AND_DEPTHS).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y); else if (irr_driver->getSSAOViz()) irr_driver->getFBO(FBO_SSAO).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y); + else if (irr_driver->getRSM()) + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y); + m_post_processing->renderPassThrough(m_rtts->getRSM().getRTT()[0]); + } else fbo->BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y); @@ -630,6 +636,8 @@ void IrrDriver::renderParticles() void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height) { + static int tick = 0; + tick++; m_scene_manager->drawAll(scene::ESNRP_CAMERA); irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION)); irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW)); @@ -710,6 +718,8 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW)); } + if (!(tick % 100)) + rsm_matrix = sun_ortho_matrix[3]; assert(sun_ortho_matrix.size() == 4); camnode->setNearValue(oldnear); camnode->setFarValue(oldfar); @@ -760,7 +770,19 @@ void IrrDriver::renderShadows() glDisable(GL_POLYGON_OFFSET_FILL); - glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height); + m_rtts->getRSM().Bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(MeshShader::RSMShader::Program); + for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) + { + const GLMesh mesh = *GroupedFPSM::MeshSet[i]; + if (!mesh.textures[0]) + continue; + compressTexture(mesh.textures[0], true); + setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + draw(mesh, mesh.vao_rsm_pass, rsm_matrix, GroupedFPSM::MVPSet[i], 0); + } } // ---------------------------------------------------------------------------- diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 96a0a757a..d8bd2a9dd 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -317,6 +317,7 @@ void Shaders::loadShaders() MeshShader::DisplaceShader::init(); MeshShader::DisplaceMaskShader::init(); MeshShader::ShadowShader::init(); + MeshShader::RSMShader::init(); MeshShader::InstancedShadowShader::init(); MeshShader::RefShadowShader::init(); MeshShader::InstancedRefShadowShader::init(); @@ -1487,6 +1488,36 @@ namespace MeshShader glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); } + GLuint RSMShader::Program; + GLuint RSMShader::attrib_position; + GLuint RSMShader::attrib_texcoord; + GLuint RSMShader::attrib_normal; + GLuint RSMShader::uniform_MM; + GLuint RSMShader::uniform_tex; + GLuint RSMShader::uniform_RSMMatrix; + + void RSMShader::init() + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/rsm.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rsm.frag").c_str()); + attrib_position = glGetAttribLocation(Program, "Position"); + uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); + attrib_texcoord = glGetAttribLocation(Program, "Texcoord"); + attrib_normal = glGetAttribLocation(Program, "Normal"); + uniform_tex = glGetUniformLocation(Program, "tex"); + uniform_RSMMatrix = glGetUniformLocation(Program, "RSMMatrix"); + GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); + glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); + } + + void RSMShader::setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &ModelMatrix, unsigned TU_tex) + { + glUniformMatrix4fv(uniform_RSMMatrix, 1, GL_FALSE, RSMMatrix.pointer()); + glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); + glUniform1i(uniform_tex, TU_tex); + } + GLuint InstancedShadowShader::Program; GLuint InstancedShadowShader::attrib_position; GLuint InstancedShadowShader::attrib_origin; diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 735dcec1f..4597e8d7f 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -336,6 +336,17 @@ public: static void setUniforms(const core::matrix4 &ModelMatrix); }; +class RSMShader +{ +public: + static GLuint Program; + static GLuint attrib_position, attrib_texcoord, attrib_normal; + static GLuint uniform_MM, uniform_tex, uniform_RSMMatrix; + + static void init(); + static void setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &ModelMatrix, unsigned TU_tex); +}; + class InstancedShadowShader { public: diff --git a/src/graphics/stkmesh.cpp b/src/graphics/stkmesh.cpp index f829d2aba..a18d95134 100644 --- a/src/graphics/stkmesh.cpp +++ b/src/graphics/stkmesh.cpp @@ -659,6 +659,7 @@ void initvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedM mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::ObjectPass1Shader::attrib_position, MeshShader::ObjectPass1Shader::attrib_texcoord, -1, MeshShader::ObjectPass1Shader::attrib_normal, -1, -1, -1, mesh.Stride); mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::ShadowShader::attrib_position, -1, -1, -1, -1, -1, -1, mesh.Stride); + mesh.vao_rsm_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::RSMShader::attrib_position, MeshShader::RSMShader::attrib_texcoord, -1, MeshShader::RSMShader::attrib_normal, -1, -1, -1, mesh.Stride); break; case FPSM_ALPHA_REF_TEXTURE: mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, diff --git a/src/graphics/stkmesh.hpp b/src/graphics/stkmesh.hpp index c11b797d7..a7e0fb19d 100644 --- a/src/graphics/stkmesh.hpp +++ b/src/graphics/stkmesh.hpp @@ -47,6 +47,7 @@ struct GLMesh { GLuint vao_glow_pass; GLuint vao_displace_pass; GLuint vao_displace_mask_pass; + GLuint vao_rsm_pass; GLuint vao_shadow_pass; GLuint vertex_buffer; GLuint index_buffer;