From a065df24b8525eee40e882e194b6294ff589ea1d Mon Sep 17 00:00:00 2001 From: Ian Curtis Date: Sun, 5 Nov 2023 23:44:27 +0000 Subject: [PATCH] Correct scroll fog attenuation logic (gm_matthew) The attenuation value effects the spot light on fog for the scroll fog layer. The old implemention was nearly correct but the paramaters for the mix function were swapped. --- Src/Graphics/New3D/New3D.cpp | 4 +- Src/Graphics/New3D/R3DScrollFog.cpp | 159 ++++++++++++++++------------ Src/Graphics/New3D/R3DScrollFog.h | 38 +++---- 3 files changed, 115 insertions(+), 86 deletions(-) diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index 742b6e5..f69b1d0 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -207,7 +207,7 @@ void CNew3D::DrawScrollFog() rgba[2] = vp.fogParams[2]; rgba[3] = vp.scrollFog; glViewport(vp.x, vp.y, vp.width, vp.height); - m_r3dScrollFog.DrawScrollFog(rgba, 0, vp.fogParams[6]); + m_r3dScrollFog.DrawScrollFog(rgba, n.viewport.scrollAtt, n.viewport.fogParams[6], n.viewport.spotFogColor, n.viewport.spotEllipse); break; } } @@ -246,7 +246,7 @@ void CNew3D::DrawAmbientFog() auto& vp = nodePtr->viewport; float rgba[] = { 0.0f, 0.0f, 0.0f, 1.0f - fogAmbient }; glViewport(vp.x, vp.y, vp.width, vp.height); - m_r3dScrollFog.DrawScrollFog(rgba, 0.0f, 1.0f); + m_r3dScrollFog.DrawScrollFog(rgba, 0.0f, 1.0f, vp.spotFogColor, vp.spotEllipse); // we assume spot light is not used } } diff --git a/Src/Graphics/New3D/R3DScrollFog.cpp b/Src/Graphics/New3D/R3DScrollFog.cpp index 4469ec5..2a75ca8 100644 --- a/Src/Graphics/New3D/R3DScrollFog.cpp +++ b/Src/Graphics/New3D/R3DScrollFog.cpp @@ -3,7 +3,7 @@ namespace New3D { -static const char *vertexShaderFog = R"glsl( + static const char* vertexShaderFog = R"glsl( #version 410 core @@ -19,13 +19,25 @@ void main(void) )glsl"; -static const char *fragmentShaderFog = R"glsl( + static const char* fragmentShaderFog = R"glsl( #version 410 core uniform float fogAttenuation; uniform float fogAmbient; uniform vec4 fogColour; +uniform vec3 spotFogColor; +uniform vec4 spotEllipse; + +// Spotlight on fog +float ellipse; +vec2 position, size; +vec3 lSpotFogColor; + +// Scroll fog +float lfogAttenuation; +vec3 lFogColor; +vec4 scrollFog; // outputs layout(location = 0) out vec4 out0; // opaque @@ -44,10 +56,21 @@ void WriteOutputs(vec4 colour) void main() { // Scroll fog base color - vec3 lFogColor = fogColour.rgb * fogAmbient; + lFogColor = fogColour.rgb * fogAmbient; + + // Spotlight on fog (area) + position = spotEllipse.xy; + size = spotEllipse.zw; + ellipse = length((gl_FragCoord.xy - position) / size); + ellipse = ellipse * ellipse; // decay rate = square of distance from center + ellipse = 1.0 - ellipse; // invert + ellipse = max(0.0, ellipse); // clamp + + // Spotlight on fog (color) + lSpotFogColor = mix(vec3(0.0), spotFogColor * ellipse * fogColour.rgb, fogAttenuation); // Scroll fog density - vec4 scrollFog = vec4(lFogColor, fogColour.a * (1.0 - fogAttenuation)); + scrollFog = vec4(lFogColor + lSpotFogColor, fogColour.a); // Final Color WriteOutputs(scrollFog); @@ -56,71 +79,75 @@ void main() )glsl"; -R3DScrollFog::R3DScrollFog(const Util::Config::Node &config) - : m_config(config), - m_vao(0) -{ - m_shaderProgram = 0; - m_vertexShader = 0; - m_fragmentShader = 0; + R3DScrollFog::R3DScrollFog(const Util::Config::Node& config) + : m_config(config), + m_vao(0) + { + m_shaderProgram = 0; + m_vertexShader = 0; + m_fragmentShader = 0; - AllocResources(); + AllocResources(); - glGenVertexArrays(1, &m_vao); - glBindVertexArray(m_vao); - // no states needed since we do it in the shader - glBindVertexArray(0); -} - -R3DScrollFog::~R3DScrollFog() -{ - DeallocResources(); - - if (m_vao) { - glDeleteVertexArrays(1, &m_vao); - m_vao = 0; - } -} - -void R3DScrollFog::DrawScrollFog(float rgba[4], float attenuation, float ambient) -{ - // some ogl states - glDepthMask (GL_FALSE); // disable z writes - glDisable (GL_DEPTH_TEST); // disable depth testing - - glBindVertexArray (m_vao); - glUseProgram (m_shaderProgram); - glUniform4fv (m_locFogColour, 1, rgba); - glUniform1f (m_locFogAttenuation, attenuation); - glUniform1f (m_locFogAmbient, ambient); - - glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); - - glUseProgram (0); - glBindVertexArray (0); - - glDisable (GL_BLEND); - glDepthMask (GL_TRUE); -} - -void R3DScrollFog::AllocResources() -{ - bool success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, m_config["VertexShaderFog"].ValueAs(), m_config["FragmentShaderFog"].ValueAs(), vertexShaderFog, fragmentShaderFog); - - m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour"); - m_locFogAttenuation = glGetUniformLocation(m_shaderProgram, "fogAttenuation"); - m_locFogAmbient = glGetUniformLocation(m_shaderProgram, "fogAmbient"); -} - -void R3DScrollFog::DeallocResources() -{ - if (m_shaderProgram) { - DestroyShaderProgram(m_shaderProgram, m_vertexShader, m_fragmentShader); + glGenVertexArrays(1, &m_vao); + glBindVertexArray(m_vao); + // no states needed since we do it in the shader + glBindVertexArray(0); } - m_shaderProgram = 0; - m_vertexShader = 0; - m_fragmentShader = 0; -} + R3DScrollFog::~R3DScrollFog() + { + DeallocResources(); + + if (m_vao) { + glDeleteVertexArrays(1, &m_vao); + m_vao = 0; + } + } + + void R3DScrollFog::DrawScrollFog(float rgba[4], float attenuation, float ambient, float spotRGB[3], float spotEllipse[4]) + { + // some ogl states + glDepthMask (GL_FALSE); // disable z writes + glDisable (GL_DEPTH_TEST); // disable depth testing + + glBindVertexArray (m_vao); + glUseProgram (m_shaderProgram); + glUniform4fv (m_locFogColour, 1, rgba); + glUniform1f (m_locFogAttenuation, attenuation); + glUniform1f (m_locFogAmbient, ambient); + glUniform3fv (m_locSpotFogColor, 1, spotRGB); + glUniform4fv (m_locSpotEllipse, 1, spotEllipse); + + glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + glUseProgram (0); + glBindVertexArray (0); + + glDisable (GL_BLEND); + glDepthMask (GL_TRUE); + } + + void R3DScrollFog::AllocResources() + { + bool success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, m_config["VertexShaderFog"].ValueAs(), m_config["FragmentShaderFog"].ValueAs(), vertexShaderFog, fragmentShaderFog); + + m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour"); + m_locFogAttenuation = glGetUniformLocation(m_shaderProgram, "fogAttenuation"); + m_locFogAmbient = glGetUniformLocation(m_shaderProgram, "fogAmbient"); + m_locSpotFogColor = glGetUniformLocation(m_shaderProgram, "spotFogColor"); + m_locSpotEllipse = glGetUniformLocation(m_shaderProgram, "spotEllipse"); + } + + void R3DScrollFog::DeallocResources() + { + if (m_shaderProgram) { + DestroyShaderProgram(m_shaderProgram, m_vertexShader, m_fragmentShader); + } + + m_shaderProgram = 0; + m_vertexShader = 0; + m_fragmentShader = 0; + } } diff --git a/Src/Graphics/New3D/R3DScrollFog.h b/Src/Graphics/New3D/R3DScrollFog.h index 8593a40..e38897a 100644 --- a/Src/Graphics/New3D/R3DScrollFog.h +++ b/Src/Graphics/New3D/R3DScrollFog.h @@ -6,32 +6,34 @@ namespace New3D { -class R3DScrollFog -{ -public: + class R3DScrollFog + { + public: - R3DScrollFog(const Util::Config::Node &config); - ~R3DScrollFog(); + R3DScrollFog(const Util::Config::Node& config); + ~R3DScrollFog(); - void DrawScrollFog(float rbga[4], float attenuation, float ambient); + void DrawScrollFog(float rbga[4], float attenuation, float ambient, float spotRGB[3], float spotEllipse[4]); -private: + private: - void AllocResources(); - void DeallocResources(); + void AllocResources(); + void DeallocResources(); - const Util::Config::Node &m_config; + const Util::Config::Node& m_config; - GLuint m_shaderProgram; - GLuint m_vertexShader; - GLuint m_fragmentShader; + GLuint m_shaderProgram; + GLuint m_vertexShader; + GLuint m_fragmentShader; - GLint m_locFogColour; - GLint m_locFogAttenuation; - GLint m_locFogAmbient; + GLint m_locFogColour; + GLint m_locFogAttenuation; + GLint m_locFogAmbient; + GLint m_locSpotFogColor; + GLint m_locSpotEllipse; - GLuint m_vao; -}; + GLuint m_vao; + }; }