diff --git a/lib/renderer.h b/lib/renderer.h index 0abb3e15..faa44e58 100644 --- a/lib/renderer.h +++ b/lib/renderer.h @@ -400,7 +400,6 @@ struct rendering_state { int8_t cur_bilinear_state; int8_t cur_zbuffer_state; - int8_t cur_fog_state; texture_type cur_texture_type; color_model cur_color_model; @@ -411,7 +410,6 @@ struct rendering_state { int cur_alpha; ddgr_color cur_color; - ddgr_color cur_fog_color; int8_t cur_texture_quality; // 0-none, 1-linear, 2-perspective diff --git a/renderer/HardwareOpenGL.cpp b/renderer/HardwareOpenGL.cpp index a77a36b3..ff446cc2 100644 --- a/renderer/HardwareOpenGL.cpp +++ b/renderer/HardwareOpenGL.cpp @@ -97,7 +97,8 @@ struct Renderer { projection_ = *projection; } - shader_.setUniformMat4f("u_transform", projection_ * view_ * model_); + shader_.setUniformMat4f("u_modelview", view_ * model_); + shader_.setUniformMat4f("u_projection", projection_); } void setTextureEnabled(GLuint index, bool enabled) { @@ -122,6 +123,20 @@ struct Renderer { setVertexData(offset, count, converted.data()); } + void setFogEnabled(bool enabled) { + shader_.setUniform1i("u_fog_enable", enabled); + } + + void setFogBorders(float nearz, float farz) { + shader_.setUniform1f("u_fog_start", nearz); + shader_.setUniform1f("u_fog_end", farz); + } + + void setFogColor(ddgr_color color) { + shader_.setUniform4fv("u_fog_color", GR_COLOR_RED(color) / 255.0f, GR_COLOR_GREEN(color) / 255.0f, + GR_COLOR_BLUE(color) / 255.0f, 1); + } + private: glm::mat4x4 model_; glm::mat4x4 view_; @@ -1367,26 +1382,12 @@ void rend_SetFlatColor(ddgr_color color) { gpu_state.cur_color = color; } // Sets the fog state to TRUE or FALSE void rend_SetFogState(int8_t state) { - if (state == gpu_state.cur_fog_state) - return; - - gpu_state.cur_fog_state = state; - if (state == 1) { - dglEnable(GL_FOG); - } else { - dglDisable(GL_FOG); - } + gRenderer->setFogEnabled(state); } // Sets the near and far plane of fog void rend_SetFogBorders(float nearz, float farz) { - // Sets the near and far plane of fog - float fogStart = nearz; - float fogEnd = farz; - - dglFogi(GL_FOG_MODE, GL_LINEAR); - dglFogf(GL_FOG_START, fogStart); - dglFogf(GL_FOG_END, fogEnd); + gRenderer->setFogBorders(nearz, farz); } void rend_SetRendererType(renderer_type state) { @@ -1668,20 +1669,7 @@ void rend_DrawLine(int x1, int y1, int x2, int y2) { // Sets the color of fog void rend_SetFogColor(ddgr_color color) { - if (color == gpu_state.cur_fog_color) - return; - - float fc[4]; - fc[0] = GR_COLOR_RED(color); - fc[1] = GR_COLOR_GREEN(color); - fc[2] = GR_COLOR_BLUE(color); - fc[3] = 1; - - fc[0] /= 255.0f; - fc[1] /= 255.0f; - fc[2] /= 255.0f; - - dglFogfv(GL_FOG_COLOR, fc); + gRenderer->setFogColor(color); } void rend_SetAlphaType(int8_t atype) { diff --git a/renderer/ShaderProgram.h b/renderer/ShaderProgram.h index 3746aa17..75ba79c1 100644 --- a/renderer/ShaderProgram.h +++ b/renderer/ShaderProgram.h @@ -182,6 +182,14 @@ struct ShaderProgram { dglUniform1i(getUniformId(name), val); } + void setUniform1f(std::string const& name, GLfloat val) { + dglUniform1f(getUniformId(name), val); + } + + void setUniform4fv(std::string const& name, GLfloat f0, GLfloat f1, GLfloat f2, GLfloat f3) { + dglUniform4f(getUniformId(name), f0, f1, f2, f3); + } + private: GLint getUniformId(std::string const& name) { auto it = uniform_cache_.find(name); diff --git a/renderer/dyna_gl.h b/renderer/dyna_gl.h index f79118c9..91cc2ece 100644 --- a/renderer/dyna_gl.h +++ b/renderer/dyna_gl.h @@ -156,9 +156,6 @@ DYNAEXTERN(glDrawArrays); DYNAEXTERN(glEnable); DYNAEXTERN(glEnableVertexAttribArray); DYNAEXTERN(glFlush); -DYNAEXTERN(glFogf); -DYNAEXTERN(glFogfv); -DYNAEXTERN(glFogi); DYNAEXTERN(glGenBuffers); DYNAEXTERN(glGenTextures); DYNAEXTERN(glGenVertexArrays); @@ -181,7 +178,9 @@ DYNAEXTERN(glShaderSource); DYNAEXTERN(glTexImage2D); DYNAEXTERN(glTexParameteri); DYNAEXTERN(glTexSubImage2D); +DYNAEXTERN(glUniform1f); DYNAEXTERN(glUniform1i); +DYNAEXTERN(glUniform4f); DYNAEXTERN(glUniformMatrix4fv); DYNAEXTERN(glUseProgram); DYNAEXTERN(glVertexAttribPointer); diff --git a/renderer/shaders/fragment.glsl b/renderer/shaders/fragment.glsl index f0a01bb9..a39be0b9 100644 --- a/renderer/shaders/fragment.glsl +++ b/renderer/shaders/fragment.glsl @@ -21,12 +21,24 @@ in vec4 vertex_color; in vec2 vertex_uv0; in vec2 vertex_uv1; +in vec4 vertex_modelview_pos; out vec4 out_color; uniform sampler2D u_texture0; uniform sampler2D u_texture1; uniform int u_texture_enable; +uniform bool u_fog_enable; +uniform vec4 u_fog_color; +uniform float u_fog_start; +uniform float u_fog_end; + +float branchless_invert_or_zero(in float value) { + // sign() returns 1 if val > 0, -1 if val < 0, and 0 if val == 0 + float sign_squared = sign(value) * sign(value); + // so this will either be 1/value, or 0/-1 + return sign_squared / (value + sign_squared - 1.0); +} void main() { @@ -37,4 +49,10 @@ void main() // signal lets this ignore a texture w/o branching. we use a bitfield to save bandwidth. * max(texture(u_texture0, vertex_uv0), vec4(float(!bool((u_texture_enable >> 0) & 1)))) * max(texture(u_texture1, vertex_uv1), vec4(float(!bool((u_texture_enable >> 1) & 1)))); + + float fog_factor = clamp((u_fog_end - length(vertex_modelview_pos)) * branchless_invert_or_zero(u_fog_end - u_fog_start), 0, 1); + // out_color is unchanged when fog_factor is 1 (ie, fog distance == u_fog_start). thus, to disable, + // fog_factor must also be 1. invert u_fog_enable (so that it is 1 when disabled) and take the max. + fog_factor = max(fog_factor, float(!u_fog_enable)); + out_color = out_color * fog_factor + (1 - fog_factor) * u_fog_color; } \ No newline at end of file diff --git a/renderer/shaders/vertex.glsl b/renderer/shaders/vertex.glsl index ef3ba31f..11909766 100644 --- a/renderer/shaders/vertex.glsl +++ b/renderer/shaders/vertex.glsl @@ -26,12 +26,15 @@ in vec2 in_uv1; out vec4 vertex_color; out vec2 vertex_uv0; out vec2 vertex_uv1; +out vec4 vertex_modelview_pos; -uniform mat4 u_transform; +uniform mat4 u_modelview; +uniform mat4 u_projection; void main() { - gl_Position = u_transform * vec4(in_pos, 1); + vertex_modelview_pos = u_modelview * vec4(in_pos, 1); + gl_Position = u_projection * vertex_modelview_pos; vertex_color = in_color; vertex_uv0 = in_uv0; vertex_uv1 = in_uv1;