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.
This commit is contained in:
Ian Curtis 2023-11-05 23:44:27 +00:00
parent aecf61762e
commit a065df24b8
3 changed files with 115 additions and 86 deletions

View file

@ -207,7 +207,7 @@ void CNew3D::DrawScrollFog()
rgba[2] = vp.fogParams[2]; rgba[2] = vp.fogParams[2];
rgba[3] = vp.scrollFog; rgba[3] = vp.scrollFog;
glViewport(vp.x, vp.y, vp.width, vp.height); 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; break;
} }
} }
@ -246,7 +246,7 @@ void CNew3D::DrawAmbientFog()
auto& vp = nodePtr->viewport; auto& vp = nodePtr->viewport;
float rgba[] = { 0.0f, 0.0f, 0.0f, 1.0f - fogAmbient }; float rgba[] = { 0.0f, 0.0f, 0.0f, 1.0f - fogAmbient };
glViewport(vp.x, vp.y, vp.width, vp.height); 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
} }
} }

View file

@ -3,7 +3,7 @@
namespace New3D { namespace New3D {
static const char *vertexShaderFog = R"glsl( static const char* vertexShaderFog = R"glsl(
#version 410 core #version 410 core
@ -19,13 +19,25 @@ void main(void)
)glsl"; )glsl";
static const char *fragmentShaderFog = R"glsl( static const char* fragmentShaderFog = R"glsl(
#version 410 core #version 410 core
uniform float fogAttenuation; uniform float fogAttenuation;
uniform float fogAmbient; uniform float fogAmbient;
uniform vec4 fogColour; 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 // outputs
layout(location = 0) out vec4 out0; // opaque layout(location = 0) out vec4 out0; // opaque
@ -44,10 +56,21 @@ void WriteOutputs(vec4 colour)
void main() void main()
{ {
// Scroll fog base color // 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 // Scroll fog density
vec4 scrollFog = vec4(lFogColor, fogColour.a * (1.0 - fogAttenuation)); scrollFog = vec4(lFogColor + lSpotFogColor, fogColour.a);
// Final Color // Final Color
WriteOutputs(scrollFog); WriteOutputs(scrollFog);
@ -56,71 +79,75 @@ void main()
)glsl"; )glsl";
R3DScrollFog::R3DScrollFog(const Util::Config::Node &config) R3DScrollFog::R3DScrollFog(const Util::Config::Node& config)
: m_config(config), : m_config(config),
m_vao(0) m_vao(0)
{ {
m_shaderProgram = 0; m_shaderProgram = 0;
m_vertexShader = 0; m_vertexShader = 0;
m_fragmentShader = 0; m_fragmentShader = 0;
AllocResources(); AllocResources();
glGenVertexArrays(1, &m_vao); glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao); glBindVertexArray(m_vao);
// no states needed since we do it in the shader // no states needed since we do it in the shader
glBindVertexArray(0); 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<std::string>(), m_config["FragmentShaderFog"].ValueAs<std::string>(), 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);
} }
m_shaderProgram = 0; R3DScrollFog::~R3DScrollFog()
m_vertexShader = 0; {
m_fragmentShader = 0; 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<std::string>(), m_config["FragmentShaderFog"].ValueAs<std::string>(), 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;
}
} }

View file

@ -6,32 +6,34 @@
namespace New3D { namespace New3D {
class R3DScrollFog class R3DScrollFog
{ {
public: public:
R3DScrollFog(const Util::Config::Node &config); R3DScrollFog(const Util::Config::Node& config);
~R3DScrollFog(); ~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 AllocResources();
void DeallocResources(); void DeallocResources();
const Util::Config::Node &m_config; const Util::Config::Node& m_config;
GLuint m_shaderProgram; GLuint m_shaderProgram;
GLuint m_vertexShader; GLuint m_vertexShader;
GLuint m_fragmentShader; GLuint m_fragmentShader;
GLint m_locFogColour; GLint m_locFogColour;
GLint m_locFogAttenuation; GLint m_locFogAttenuation;
GLint m_locFogAmbient; GLint m_locFogAmbient;
GLint m_locSpotFogColor;
GLint m_locSpotEllipse;
GLuint m_vao; GLuint m_vao;
}; };
} }