Supermodel/Src/Graphics/New3D/R3DScrollFog.cpp
Ian Curtis 40c8259130 Rewrite the whole project for GL4+. I figured if we removed the limitation of a legacy rendering API we could improve things a bit. With GL4+ we can do unsigned integer math in the shaders. This allows us to upload a direct copy of the real3d texture sheet, and texture directly from this memory given the x/y pos and type. This massively simplifies the binding and invalidation code. Also the crazy corner cases will work because it essentially works the same way as the original hardware.
The standard triangle render requires gl 4.1 core, so should work on mac. The quad renderer runs on 4.5 core. The legacy renderer should still work, and when enabled a regular opengl context will be created, which allows functions marked depreciated in the core profiles to still work. This will only work in windows/linux I think. Apple doesn't support this.

A GL 4.1 GPU is now the min required spec. Sorry if you have an OLDER gpu. GL 4.1 is over 12 years old now.

This is a big update so I apologise in advance if I accidently broke something :]
2022-11-07 21:33:01 +00:00

146 lines
3.5 KiB
C++

#include "R3DScrollFog.h"
#include "Graphics/Shader.h"
namespace New3D {
static const char *vertexShaderFog = R"glsl(
#version 410 core
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];
}
)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
out vec4 fragColor;
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
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;
}
)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()
{
DeallocResources();
if (m_vao) {
glDeleteVertexArrays(1, &m_vao);
m_vao = 0;
}
}
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);
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;
}
}