diff --git a/data/shaders/logluminance.frag b/data/shaders/logluminance.frag index 309bbde40..10f3d4000 100644 --- a/data/shaders/logluminance.frag +++ b/data/shaders/logluminance.frag @@ -9,7 +9,6 @@ void main() { vec3 weight = vec3(0.2125f, 0.7154f, 0.0721f); vec3 col = texture(tex, uv).xyz; - // TODO: Investigate why color buffer has negative value sometimes - float luma = max(dot(col, weight), 0.); + float luma = dot(col, weight); FragColor = vec4(log(luma + delta)); } \ No newline at end of file diff --git a/data/shaders/normalmap.frag b/data/shaders/normalmap.frag index acb1dfd8a..255942efd 100644 --- a/data/shaders/normalmap.frag +++ b/data/shaders/normalmap.frag @@ -1,31 +1,24 @@ uniform sampler2D normalMap; +uniform sampler2D DiffuseForAlpha; -#if __VERSION__ >= 130 in vec3 tangent; in vec3 bitangent; in vec2 uv; out vec3 EncodedNormal; -#else -varying vec3 tangent; -varying vec3 bitangent; -varying vec2 uv; -#define EncodedNormal gl_FragColor.xy -#endif - - vec2 EncodeNormal(vec3 n); void main() { - // normal in Tangent Space - vec3 TS_normal = 2.0 * texture(normalMap, uv).rgb - 1.0; - // Because of interpolation, we need to renormalize - vec3 Frag_tangent = normalize(tangent); - vec3 Frag_normal = normalize(cross(Frag_tangent, bitangent)); - vec3 Frag_bitangent = cross(Frag_normal, Frag_tangent); + // normal in Tangent Space + vec3 TS_normal = 2.0 * texture(normalMap, uv).rgb - 1.0; + float alpha = texture(DiffuseForAlpha, uv).a; + // Because of interpolation, we need to renormalize + vec3 Frag_tangent = normalize(tangent); + vec3 Frag_normal = normalize(cross(Frag_tangent, bitangent)); + vec3 Frag_bitangent = cross(Frag_normal, Frag_tangent); - vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal; - EncodedNormal.xy = 0.5 * EncodeNormal(normalize(FragmentNormal)) + 0.5; - EncodedNormal.z = 1.; + vec3 FragmentNormal = TS_normal.x * Frag_tangent + TS_normal.y * Frag_bitangent - TS_normal.z * Frag_normal; + EncodedNormal.xy = 0.5 * EncodeNormal(normalize(FragmentNormal)) + 0.5; + EncodedNormal.z = exp2(10. * (1. - alpha) + 1.); } diff --git a/data/shaders/ssao.frag b/data/shaders/ssao.frag index 92e34966c..4e3cbaa7c 100644 --- a/data/shaders/ssao.frag +++ b/data/shaders/ssao.frag @@ -66,5 +66,5 @@ void main(void) bl += isOccluded ? samplePoints[i].z * smoothstep(5 * radius, 0, distance(samplePos, FragPos)) : 0.; } - AO = 1.0 - bl * invSamples; + AO = max(1.0 - bl * invSamples, 0.); } diff --git a/data/shaders/tonemap.frag b/data/shaders/tonemap.frag index b0b5b9b2e..9e23b9bc5 100644 --- a/data/shaders/tonemap.frag +++ b/data/shaders/tonemap.frag @@ -1,4 +1,4 @@ -#define AUTO_EXPOSURE +// From http://www.ceng.metu.edu.tr/~akyuz/files/hdrgpu.pdf uniform sampler2D tex; uniform sampler2D logluminancetex; @@ -9,19 +9,23 @@ out vec4 FragColor; vec3 getCIEYxy(vec3 rgbColor); vec3 getRGBFromCIEXxy(vec3 YxyColor); -float exposure = .2; -float whitePoint = 10.; +float exposure = .09; +float Lwhite = 1.; float delta = .0001; +float saturation = 1.; void main() { vec4 col = texture(tex, uv); - float avgLuminance = textureLod(logluminancetex, uv, 10.).x; - avgLuminance = max(exp(avgLuminance) - delta, delta); + float avgLw = textureLod(logluminancetex, uv, 10.).x; + avgLw = max(exp(avgLw) - delta, delta); - vec3 Yxy = getCIEYxy(col.xyz); - float Lp = Yxy.r * exposure / avgLuminance; - Yxy.r = (Lp * (1. + Lp / (whitePoint * whitePoint))) / (1. + Lp); - FragColor = vec4(getRGBFromCIEXxy(Yxy), 1.); + vec3 Cw = getCIEYxy(col.xyz); + float Lw = Cw.y; + float L = Lw * exposure / avgLw; + float Ld = L * (1. + L / (Lwhite * Lwhite)); + Ld /= (1. + L); + + FragColor = vec4(Ld * pow(col.xyz / Lw, vec3(saturation)), 1.); } diff --git a/data/shaders/utils/getCIEXYZ.frag b/data/shaders/utils/getCIEXYZ.frag index 607f4e396..8776b7fdf 100644 --- a/data/shaders/utils/getCIEXYZ.frag +++ b/data/shaders/utils/getCIEXYZ.frag @@ -3,15 +3,10 @@ vec3 getCIEYxy(vec3 rgbColor) { - // convert rgb to srgb - vec3 sRGBColor = rgbColor;//vec3(pow(rgbColor.x, 1. / 2.2), pow(rgbColor.y, 1. / 2.2), pow(rgbColor.z, 1. / 2.2)); - mat3 sRGB2XYZ = transpose(mat3( vec3(.4125, .2126, .0193), vec3(.3576, .7152, .1192), vec3(.1805, .0722, .9505))); - vec3 XYZ = sRGB2XYZ * sRGBColor; - float sum = dot(vec3(1.), XYZ); - return vec3(XYZ.y, XYZ.xy / sum); -} \ No newline at end of file + return sRGB2XYZ * rgbColor; +} diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index a7a5b6c7f..70f71565a 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -637,10 +637,77 @@ void PostProcessing::render() glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); - computeLogLuminance(in_rtt); - toneMap(out_fbo, in_rtt); - std::swap(in_rtt, out_rtt); - std::swap(in_fbo, out_fbo); + PROFILER_PUSH_CPU_MARKER("- Godrays", 0xFF, 0x00, 0x00); + if (UserConfigParams::m_light_shaft && m_sunpixels > 30)//World::getWorld()->getTrack()->hasGodRays() && ) // god rays + { + glEnable(GL_DEPTH_TEST); + // Grab the sky + glBindFramebuffer(GL_FRAMEBUFFER, out_fbo); + glClear(GL_COLOR_BUFFER_BIT); + irr_driver->renderSkybox(); + + // Set the sun's color + const SColor col = World::getWorld()->getTrack()->getSunColor(); + ColorizeProvider * const colcb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE); + colcb->setColor(col.getRed() / 255.0f, col.getGreen() / 255.0f, col.getBlue() / 255.0f); + + // The sun interposer + STKMeshSceneNode *sun = irr_driver->getSunInterposer(); + irr_driver->getSceneManager()->drawAll(ESNRP_CAMERA); + irr_driver->setPhase(GLOW_PASS); + sun->render(); + glDisable(GL_DEPTH_TEST); + + // Fade to quarter + glBindFramebuffer(GL_FRAMEBUFFER, irr_driver->getFBO(FBO_QUARTER1)); + glViewport(0, 0, UserConfigParams::m_width / 4, UserConfigParams::m_height / 4); + renderGodFade(out_rtt, col); + + // Blur + renderGaussian3Blur(irr_driver->getFBO(FBO_QUARTER1), irr_driver->getRenderTargetTexture(RTT_QUARTER1), + irr_driver->getFBO(FBO_QUARTER2), irr_driver->getRenderTargetTexture(RTT_QUARTER2), + UserConfigParams::m_width / 4, + UserConfigParams::m_height / 4); + + + + // Calculate the sun's position in texcoords + const core::vector3df pos = sun->getPosition(); + float ndc[4]; + core::matrix4 trans = camnode->getProjectionMatrix(); + trans *= camnode->getViewMatrix(); + + trans.transformVect(ndc, pos); + + const float texh = m_vertices[cam].v1.TCoords.Y - m_vertices[cam].v0.TCoords.Y; + const float texw = m_vertices[cam].v3.TCoords.X - m_vertices[cam].v0.TCoords.X; + + const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f) * texw; + const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f) * texh; + + // Rays please + glBindFramebuffer(GL_FRAMEBUFFER, irr_driver->getFBO(FBO_QUARTER2)); + renderGodRay(irr_driver->getRenderTargetTexture(RTT_QUARTER1), core::vector2df(sunx, suny)); + + // Blur + renderGaussian3Blur(irr_driver->getFBO(FBO_QUARTER2), irr_driver->getRenderTargetTexture(RTT_QUARTER2), + irr_driver->getFBO(FBO_QUARTER1), irr_driver->getRenderTargetTexture(RTT_QUARTER1), + UserConfigParams::m_width / 4, + UserConfigParams::m_height / 4); + + glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height); + // Blend + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + + glBindFramebuffer(GL_FRAMEBUFFER, in_fbo); + renderPassThrough(irr_driver->getRenderTargetTexture(RTT_QUARTER2)); + glDisable(GL_BLEND); + } + PROFILER_POP_CPU_MARKER(); + + // Simulate camera defects from there PROFILER_PUSH_CPU_MARKER("- Bloom", 0xFF, 0x00, 0x00); if (UserConfigParams::m_bloom) @@ -696,78 +763,12 @@ void PostProcessing::render() renderPassThrough(irr_driver->getRenderTargetTexture(RTT_BLOOM_512)); glDisable(GL_BLEND); } // end if bloom - PROFILER_POP_CPU_MARKER(); - PROFILER_PUSH_CPU_MARKER("- Godrays", 0xFF, 0x00, 0x00); - if (UserConfigParams::m_light_shaft && m_sunpixels > 30)//World::getWorld()->getTrack()->hasGodRays() && ) // god rays - { - glEnable(GL_DEPTH_TEST); - // Grab the sky - glBindFramebuffer(GL_FRAMEBUFFER, out_fbo); - glClear(GL_COLOR_BUFFER_BIT); - irr_driver->renderSkybox(); - - // Set the sun's color - const SColor col = World::getWorld()->getTrack()->getSunColor(); - ColorizeProvider * const colcb = (ColorizeProvider *) irr_driver->getCallback(ES_COLORIZE); - colcb->setColor(col.getRed() / 255.0f, col.getGreen() / 255.0f, col.getBlue() / 255.0f); - - // The sun interposer - STKMeshSceneNode *sun = irr_driver->getSunInterposer(); - irr_driver->getSceneManager()->drawAll(ESNRP_CAMERA); - irr_driver->setPhase(GLOW_PASS); - sun->render(); - glDisable(GL_DEPTH_TEST); - - // Fade to quarter - glBindFramebuffer(GL_FRAMEBUFFER, irr_driver->getFBO(FBO_QUARTER1)); - glViewport(0, 0, UserConfigParams::m_width / 4, UserConfigParams::m_height / 4); - renderGodFade(out_rtt, col); - - // Blur - renderGaussian3Blur(irr_driver->getFBO(FBO_QUARTER1), irr_driver->getRenderTargetTexture(RTT_QUARTER1), - irr_driver->getFBO(FBO_QUARTER2), irr_driver->getRenderTargetTexture(RTT_QUARTER2), - UserConfigParams::m_width / 4, - UserConfigParams::m_height / 4); - - - - // Calculate the sun's position in texcoords - const core::vector3df pos = sun->getPosition(); - float ndc[4]; - core::matrix4 trans = camnode->getProjectionMatrix(); - trans *= camnode->getViewMatrix(); - - trans.transformVect(ndc, pos); - - const float texh = m_vertices[cam].v1.TCoords.Y - m_vertices[cam].v0.TCoords.Y; - const float texw = m_vertices[cam].v3.TCoords.X - m_vertices[cam].v0.TCoords.X; - - const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f) * texw; - const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f) * texh; - - // Rays please - glBindFramebuffer(GL_FRAMEBUFFER, irr_driver->getFBO(FBO_QUARTER2)); - renderGodRay(irr_driver->getRenderTargetTexture(RTT_QUARTER1), core::vector2df(sunx, suny)); - - // Blur - renderGaussian3Blur(irr_driver->getFBO(FBO_QUARTER2), irr_driver->getRenderTargetTexture(RTT_QUARTER2), - irr_driver->getFBO(FBO_QUARTER1), irr_driver->getRenderTargetTexture(RTT_QUARTER1), - UserConfigParams::m_width / 4, - UserConfigParams::m_height / 4); - - glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height); - // Blend - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - glBlendEquation(GL_FUNC_ADD); - - glBindFramebuffer(GL_FRAMEBUFFER, in_fbo); - renderPassThrough(irr_driver->getRenderTargetTexture(RTT_QUARTER2)); - glDisable(GL_BLEND); - } - PROFILER_POP_CPU_MARKER(); + computeLogLuminance(in_rtt); + toneMap(out_fbo, in_rtt); + std::swap(in_rtt, out_rtt); + std::swap(in_fbo, out_fbo); if (UserConfigParams::m_motionblur && m_any_boost) // motion blur { @@ -778,11 +779,6 @@ void PostProcessing::render() PROFILER_POP_CPU_MARKER(); } - glBindFramebuffer(GL_FRAMEBUFFER, out_fbo); - renderColorLevel(in_rtt); - std::swap(in_fbo, out_fbo); - std::swap(in_rtt, out_rtt); - if (irr_driver->getNormals()) { glEnable(GL_FRAMEBUFFER_SRGB); diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index c6a5ec32b..386cb7f27 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -518,6 +518,7 @@ namespace MeshShader GLuint NormalMapShader::uniform_MM; GLuint NormalMapShader::uniform_IMM; GLuint NormalMapShader::uniform_normalMap; + GLuint NormalMapShader::uniform_DiffuseForAlpha; void NormalMapShader::init() { @@ -532,17 +533,19 @@ namespace MeshShader uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); uniform_IMM = glGetUniformLocation(Program, "InverseModelMatrix"); uniform_normalMap = glGetUniformLocation(Program, "normalMap"); + uniform_DiffuseForAlpha = glGetUniformLocation(Program, "DiffuseForAlpha"); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } - void NormalMapShader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, unsigned TU_normalMap) + void NormalMapShader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, unsigned TU_normalMap, unsigned TU_uniform_DiffuseForAlpha) { if (UserConfigParams::m_ubo_disabled) bypassUBO(Program); glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); glUniformMatrix4fv(uniform_IMM, 1, GL_FALSE, InverseModelMatrix.pointer()); glUniform1i(uniform_normalMap, TU_normalMap); + glUniform1i(uniform_DiffuseForAlpha, TU_uniform_DiffuseForAlpha); } GLuint InstancedObjectPass1Shader::Program; diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 4e3c9f671..04ded8e33 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -72,10 +72,10 @@ class NormalMapShader public: static GLuint Program; static GLuint attrib_position, attrib_texcoord, attrib_tangent, attrib_bitangent; - static GLuint uniform_MM, uniform_IMM, uniform_normalMap; + static GLuint uniform_MM, uniform_IMM, uniform_normalMap, uniform_DiffuseForAlpha; static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, unsigned TU_normalMap); + static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, unsigned TU_normalMap, unsigned TU_uniform_DiffuseForAlpha); }; class InstancedObjectPass1Shader diff --git a/src/graphics/stkmesh.cpp b/src/graphics/stkmesh.cpp index e1fc81da3..61ab151b4 100644 --- a/src/graphics/stkmesh.cpp +++ b/src/graphics/stkmesh.cpp @@ -292,8 +292,10 @@ void drawNormalPass(const GLMesh &mesh, const core::matrix4 & ModelMatrix, const assert(mesh.textures[1]); compressTexture(mesh.textures[1], false); setTexture(0, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + compressTexture(mesh.textures[0], true); + setTexture(1, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - MeshShader::NormalMapShader::setUniforms(ModelMatrix, InverseModelMatrix, 0); + MeshShader::NormalMapShader::setUniforms(ModelMatrix, InverseModelMatrix, 0, 1); assert(mesh.vao_first_pass); glBindVertexArray(mesh.vao_first_pass);