Supermodel/Src/Graphics/New3D/R3DScrollFog.cpp

146 lines
3.5 KiB
C++
Raw Normal View History

#include "R3DScrollFog.h"
#include "Graphics/Shader.h"
namespace New3D {
2017-07-08 10:55:14 +00:00
static const char *vertexShaderFog = R"glsl(
#version 410 core
2017-07-08 10:55:14 +00:00
void main(void)
{
const vec4 vertices[] = vec4[](vec4(-1.0, -1.0, 0.0, 1.0),
vec4(-1.0, 1.0, 0.0, 1.0),
vec4( 1.0, -1.0, 0.0, 1.0),
vec4( 1.0, 1.0, 0.0, 1.0));
gl_Position = vertices[gl_VertexID % 4];
}
2017-07-08 10:55:14 +00:00
)glsl";
static const char *fragmentShaderFog = R"glsl(
#version 410 core
2017-07-08 10:55:14 +00:00
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
out vec4 fragColor;
2017-07-08 10:55:14 +00:00
void main()
{
// Scroll fog base color
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
2017-07-08 10:55:14 +00:00
ellipse = 1.0 - ellipse; // invert
ellipse = max(0.0, ellipse); // clamp
// Spotlight on fog (color)
lSpotFogColor = mix(spotFogColor * ellipse * fogColour.rgb, vec3(0.0), fogAttenuation);
// Scroll fog density
scrollFog = vec4(lFogColor + lSpotFogColor, fogColour.a);
// Final Color
fragColor = scrollFog;
}
2017-07-08 10:55:14 +00:00
)glsl";
R3DScrollFog::R3DScrollFog(const Util::Config::Node &config)
: m_config(config),
m_vao(0)
{
m_shaderProgram = 0;
m_vertexShader = 0;
m_fragmentShader = 0;
AllocResources();
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
// no states needed since we do it in the shader
glBindVertexArray(0);
}
R3DScrollFog::~R3DScrollFog()
{
2017-07-08 10:55:14 +00:00
DeallocResources();
if (m_vao) {
glDeleteVertexArrays(1, &m_vao);
m_vao = 0;
}
2017-07-08 10:55:14 +00:00
}
void R3DScrollFog::DrawScrollFog(float rgba[4], float attenuation, float ambient, float *spotRGB, float *spotEllipse)
{
// some ogl states
glDepthMask (GL_FALSE); // disable z writes
glDisable (GL_DEPTH_TEST); // disable depth testing
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2017-07-08 10:55:14 +00:00
glBindVertexArray (m_vao);
2017-07-08 10:55:14 +00:00
glUseProgram (m_shaderProgram);
glUniform4fv (m_locFogColour, 1, rgba);
2017-07-08 10:55:14 +00:00
glUniform1f (m_locFogAttenuation, attenuation);
glUniform1f (m_locFogAmbient, ambient);
glUniform3fv (m_locSpotFogColor, 1, spotRGB);
glUniform4fv (m_locSpotEllipse, 1, spotEllipse);
2017-07-08 10:55:14 +00:00
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);
2017-07-08 10:55:14 +00:00
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;
}
}