From 6a3556b4badcf136c375395d2eab780c5bc51a71 Mon Sep 17 00:00:00 2001 From: vlj Date: Thu, 3 Apr 2014 14:46:35 +0200 Subject: [PATCH] Shaders'outputs use premultiplied alphas --- data/shaders/billboard.frag | 3 +- data/shaders/bubble.frag | 5 +- data/shaders/particle.frag | 5 +- data/shaders/transparent.frag | 4 +- data/shaders/transparentfog.frag | 3 +- src/graphics/gpuparticles.cpp | 6 +- src/graphics/irr_driver.hpp | 4 ++ src/graphics/render.cpp | 114 ++++++++++++++++++------------- 8 files changed, 88 insertions(+), 56 deletions(-) diff --git a/data/shaders/billboard.frag b/data/shaders/billboard.frag index 9a9de2c5e..6df5ad558 100644 --- a/data/shaders/billboard.frag +++ b/data/shaders/billboard.frag @@ -11,5 +11,6 @@ varying vec2 uv; void main(void) { - FragColor = texture(tex, uv); + vec4 color = texture(tex, uv); + FragColor = vec4(color.rgb * color.a, color.a); } diff --git a/data/shaders/bubble.frag b/data/shaders/bubble.frag index 6f69dfa74..f523d50af 100644 --- a/data/shaders/bubble.frag +++ b/data/shaders/bubble.frag @@ -29,6 +29,7 @@ varying vec2 uv; void main() { - FragColor = texture(tex, uv); - FragColor.a *= transparency; + vec4 Color = texture(tex, uv); + Color.a *= transparency; + FragColor = vec4(Color.rgb * Color.a, Color.a); } diff --git a/data/shaders/particle.frag b/data/shaders/particle.frag index 6e6212916..f363e9cf1 100644 --- a/data/shaders/particle.frag +++ b/data/shaders/particle.frag @@ -6,7 +6,7 @@ uniform vec2 screen; in float lf; in vec2 tc; in vec3 pc; -out vec4 color; +out vec4 FragColor; void main(void) @@ -19,6 +19,7 @@ void main(void) vec4 EnvPos = invproj * (2. * vec4(xy, EnvZ, 1.0) - 1.); EnvPos /= EnvPos.w; float alpha = clamp((EnvPos.z - FragmentPos.z) * 0.3, 0., 1.); - color = texture(tex, tc) * vec4(pc, 1.0); + vec4 color = texture(tex, tc) * vec4(pc, 1.0); color.a *= alpha * smoothstep(1., 0.8, lf); + FragColor = vec4(color.rgb * color.a, color.a); } diff --git a/data/shaders/transparent.frag b/data/shaders/transparent.frag index f6585ef9d..25add3aec 100644 --- a/data/shaders/transparent.frag +++ b/data/shaders/transparent.frag @@ -12,5 +12,7 @@ varying vec2 uv; void main() { - FragColor = texture(tex, uv) * color; + vec4 Color = texture(tex, uv) * color; + // Premultiply alpha + FragColor = vec4(Color.rgb * Color.a, Color.a); } diff --git a/data/shaders/transparentfog.frag b/data/shaders/transparentfog.frag index b5084f5a5..4d7e798b3 100644 --- a/data/shaders/transparentfog.frag +++ b/data/shaders/transparentfog.frag @@ -34,5 +34,6 @@ void main() fog = min(fog, fogmax); - FragColor = vec4(vec4(col, 0.) * fog + diffusecolor *(1. - fog)); + vec4 color = vec4(vec4(col, 0.) * fog + diffusecolor *(1. - fog)); + FragColor = vec4(color.rgb * color.a, color.a); } diff --git a/src/graphics/gpuparticles.cpp b/src/graphics/gpuparticles.cpp index a03d88b0a..e5684fdfb 100644 --- a/src/graphics/gpuparticles.cpp +++ b/src/graphics/gpuparticles.cpp @@ -435,7 +435,7 @@ void ParticleSystemProxy::simulate() void ParticleSystemProxy::drawFlip() { - glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendFunc(GL_ONE, GL_ONE); glUseProgram(ParticleShader::FlipParticleRender::Program); float screen[2] = { @@ -455,9 +455,9 @@ void ParticleSystemProxy::drawFlip() void ParticleSystemProxy::drawNotFlip() { if (m_alpha_additive) - glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendFunc(GL_ONE, GL_ONE); else - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glUseProgram(ParticleShader::SimpleParticleRender::Program); float screen[2] = { diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 381248cff..ebf8c288b 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -222,6 +222,10 @@ private: void renderFixed(float dt); void renderGLSL(float dt); + void renderSolidFirstPass(); + void renderSolidSecondPass(); + void renderTransparent(); + void renderParticles(); void renderShadows(//ShadowImportanceProvider * const sicb, scene::ICameraSceneNode * const camnode, //video::SOverrideMaterial &overridemat, diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 4a3bf90be..bfefae5b1 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -172,21 +172,10 @@ void IrrDriver::renderGLSL(float dt) }*/ // Fire up the MRT - irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH), false, false); - PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00); - m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_SOLID; - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDepthMask(GL_TRUE); - glDisable(GL_BLEND); - glEnable(GL_CULL_FACE); - irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS); - m_scene_manager->drawAll(m_renderpass); - irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION)); - irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW)); - irr_driver->genProjViewMatrix(); - PROFILER_POP_CPU_MARKER(); + PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00); + renderSolidFirstPass(); + PROFILER_POP_CPU_MARKER(); + // Todo : reenable glow and shadows //ShadowImportanceProvider * const sicb = (ShadowImportanceProvider *) @@ -212,21 +201,7 @@ void IrrDriver::renderGLSL(float dt) PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("- Solid Pass 2", 0x00, 0x00, 0xFF); - irr_driver->setPhase(SOLID_LIT_PASS); - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDepthMask(GL_FALSE); - glDisable(GL_BLEND); - m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_SOLID; - setTexture(0, getTextureGLuint(irr_driver->getRTT(RTT_TMP1)), GL_NEAREST, GL_NEAREST); - setTexture(1, getTextureGLuint(irr_driver->getRTT(RTT_TMP2)), GL_NEAREST, GL_NEAREST); - setTexture(2, getTextureGLuint(irr_driver->getRTT(RTT_SSAO)), GL_NEAREST, GL_NEAREST); - if (!UserConfigParams::m_ssao) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ONE }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - m_scene_manager->drawAll(m_renderpass); + renderSolidSecondPass(); PROFILER_POP_CPU_MARKER(); if (World::getWorld()->getTrack()->isFogEnabled()) @@ -284,25 +259,11 @@ void IrrDriver::renderGLSL(float dt) // We need to re-render camera due to the per-cam-node hack. PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00); - irr_driver->setPhase(TRANSPARENT_PASS); - m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT; - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - m_scene_manager->drawAll(m_renderpass); + renderTransparent(); PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00); - m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT_EFFECT; - glDepthMask(GL_FALSE); - glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - m_scene_manager->drawAll(m_renderpass); + renderParticles(); PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("- Displacement", 0x00, 0x00, 0xFF); @@ -445,6 +406,67 @@ void IrrDriver::renderFixed(float dt) // ---------------------------------------------------------------------------- +void IrrDriver::renderSolidFirstPass() +{ + irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH), false, false); + + m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_SOLID; + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDepthMask(GL_TRUE); + glDisable(GL_BLEND); + glEnable(GL_CULL_FACE); + irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS); + m_scene_manager->drawAll(m_renderpass); + irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION)); + irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW)); + irr_driver->genProjViewMatrix(); +} + +void IrrDriver::renderSolidSecondPass() +{ + irr_driver->setPhase(SOLID_LIT_PASS); + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_BLEND); + m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_SOLID; + setTexture(0, getTextureGLuint(irr_driver->getRTT(RTT_TMP1)), GL_NEAREST, GL_NEAREST); + setTexture(1, getTextureGLuint(irr_driver->getRTT(RTT_TMP2)), GL_NEAREST, GL_NEAREST); + setTexture(2, getTextureGLuint(irr_driver->getRTT(RTT_SSAO)), GL_NEAREST, GL_NEAREST); + if (!UserConfigParams::m_ssao) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ONE }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + m_scene_manager->drawAll(m_renderpass); +} + +void IrrDriver::renderTransparent() +{ + irr_driver->setPhase(TRANSPARENT_PASS); + m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT; + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + m_scene_manager->drawAll(m_renderpass); +} + +void IrrDriver::renderParticles() +{ + m_renderpass = scene::ESNRP_CAMERA | scene::ESNRP_TRANSPARENT_EFFECT; + glDepthMask(GL_FALSE); + glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + m_scene_manager->drawAll(m_renderpass); +} + void IrrDriver::renderShadows(//ShadowImportanceProvider * const sicb, scene::ICameraSceneNode * const camnode, //video::SOverrideMaterial &overridemat,