gles2: calculate fog depth in vertex shader in case highp not supported

Mali-400/450 don't support highp floats in the fragment shader. This
causes overflows when computing fog density in some game scenes. To work
around that, calculate fog density in vertex shader and use
interpolation.
vulkan,gl: Get rid of extra_depth_scale in fragment shader by
integrating it in fog density
This commit is contained in:
Flyinghead 2019-11-14 22:10:40 +01:00
parent 09f5d25133
commit 78eb1829d8
9 changed files with 52 additions and 58 deletions

View File

@ -8,7 +8,6 @@ struct gl4PipelineShader
{
GLuint program;
GLuint extra_depth_scale;
GLuint pp_ClipTest,cp_AlphaTestValue;
GLuint sp_FOG_COL_RAM,sp_FOG_COL_VERT,sp_FOG_DENSITY;
GLuint shade_scale_factor;
@ -225,7 +224,6 @@ void gl4SetupModvolVBO();
extern struct gl4ShaderUniforms_t
{
float PT_ALPHA;
float extra_depth_scale;
float fog_den_float;
float ps_FOG_COL_RAM[3];
float ps_FOG_COL_VERT[3];
@ -250,9 +248,6 @@ extern struct gl4ShaderUniforms_t
if (s->cp_AlphaTestValue!=-1)
glUniform1f(s->cp_AlphaTestValue,PT_ALPHA);
if (s->extra_depth_scale != -1)
glUniform1f(s->extra_depth_scale, extra_depth_scale);
if (s->sp_FOG_DENSITY!=-1)
glUniform1f( s->sp_FOG_DENSITY,fog_den_float);

View File

@ -120,7 +120,6 @@ uniform int shading_instr[2];
uniform int fog_control[2];
#endif
uniform highp float extra_depth_scale;
/* Vertex input*/
INTERPOLATION in lowp vec4 vtx_base;
INTERPOLATION in lowp vec4 vtx_offs;
@ -131,7 +130,7 @@ INTERPOLATION in lowp vec4 vtx_offs1;
lowp float fog_mode2(highp float w)
{
highp float z = clamp(w * extra_depth_scale * sp_FOG_DENSITY, 1.0, 255.9999);
highp float z = clamp(w * sp_FOG_DENSITY, 1.0, 255.9999);
highp float exp = floor(log2(z));
highp float m = z * 16.0 / pow(2.0, exp) - 16.0;
float idx = floor(m) + exp * 16.0 + 0.5;
@ -421,8 +420,6 @@ bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *pixel_source /*
glUniform1i(gu, 1);
//get the uniform locations
s->extra_depth_scale = glGetUniformLocation(s->program, "extra_depth_scale");
s->pp_ClipTest = glGetUniformLocation(s->program, "pp_ClipTest");
s->sp_FOG_DENSITY = glGetUniformLocation(s->program, "sp_FOG_DENSITY");
@ -670,8 +667,6 @@ static bool RenderFrame()
}
resize(rendering_width, rendering_height);
gl4ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale;
//DEBUG_LOG(RENDERER, "scale: %f, %f, %f, %f", gl4ShaderUniforms.scale_coefs[0], gl4ShaderUniforms.scale_coefs[1], gl4ShaderUniforms.scale_coefs[2], gl4ShaderUniforms.scale_coefs[3]);
//VERT and RAM fog color constants
@ -689,7 +684,7 @@ static bool RenderFrame()
u8* fog_density=(u8*)&FOG_DENSITY;
float fog_den_mant=fog_density[1]/128.0f; //bit 7 -> x. bit, so [6:0] -> fraction -> /128
s32 fog_den_exp=(s8)fog_density[0];
gl4ShaderUniforms.fog_den_float=fog_den_mant*powf(2.0f,fog_den_exp);
gl4ShaderUniforms.fog_den_float = fog_den_mant * powf(2.0f,fog_den_exp) * settings.rend.ExtraDepthScale;
gl4ShaderUniforms.fog_clamp_min[0] = ((pvrrc.fog_clamp_min >> 16) & 0xFF) / 255.0f;
gl4ShaderUniforms.fog_clamp_min[1] = ((pvrrc.fog_clamp_min >> 8) & 0xFF) / 255.0f;

View File

@ -57,9 +57,10 @@ const char* VertexShaderSource = R"(
#endif
/* Vertex constants*/
uniform highp vec4 scale;
uniform highp vec4 depth_scale;
uniform highp mat4 normal_matrix;
uniform highp float sp_FOG_DENSITY;
/* Vertex input */
in highp vec4 in_pos;
in lowp vec4 in_base;
@ -69,6 +70,9 @@ in mediump vec2 in_uv;
INTERPOLATION out lowp vec4 vtx_base;
INTERPOLATION out lowp vec4 vtx_offs;
out mediump vec2 vtx_uv;
#if TARGET_GL == GLES2
out highp float fog_depth;
#endif
void main()
{
vtx_base = in_base;
@ -86,7 +90,8 @@ void main()
#if TARGET_GL != GLES2
vpos.z = vpos.w;
#else
vpos.z = depth_scale.x + depth_scale.y * vpos.w;
fog_depth = vpos.z * sp_FOG_DENSITY;
vpos.z = depth_scale.x + depth_scale.y * vpos.w;
#endif
vpos.xy *= vpos.w;
gl_Position = vpos;
@ -136,7 +141,6 @@ out highp vec4 FragColor;
#define FOG_CHANNEL a
#endif
#if TARGET_GL == GL3 || TARGET_GL == GLES3
#if pp_Gouraud == 0
#define INTERPOLATION flat
@ -157,18 +161,24 @@ uniform sampler2D tex,fog_table;
uniform lowp float trilinear_alpha;
uniform lowp vec4 fog_clamp_min;
uniform lowp vec4 fog_clamp_max;
uniform highp float extra_depth_scale;
/* Vertex input*/
INTERPOLATION in lowp vec4 vtx_base;
INTERPOLATION in lowp vec4 vtx_offs;
in mediump vec2 vtx_uv;
#if TARGET_GL == GLES2
in highp float fog_depth;
#endif
lowp float fog_mode2(highp float w)
{
highp float z = clamp(w * extra_depth_scale * sp_FOG_DENSITY, 1.0, 255.9999);
highp float exp = floor(log2(z));
#if TARGET_GL == GLES2
highp float z = clamp(fog_depth, 1.0, 255.9999);
#else
highp float z = clamp(w * sp_FOG_DENSITY, 1.0, 255.9999);
#endif
mediump float exp = floor(log2(z));
highp float m = z * 16.0 / pow(2.0, exp) - 16.0;
lowp float idx = floor(m) + exp * 16.0 + 0.5;
mediump float idx = floor(m) + exp * 16.0 + 0.5;
highp vec4 fog_coef = texture(fog_table, vec2(idx / 128.0, 0.75 - (m - floor(m)) / 2.0));
return fog_coef.FOG_CHANNEL;
}
@ -432,7 +442,7 @@ void do_swap_automation()
static void gl_delete_shaders()
{
for (auto it : gl.shaders)
for (const auto& it : gl.shaders)
{
if (it.second.program != 0)
glcache.DeleteProgram(it.second.program);
@ -505,6 +515,10 @@ void findGLVersion()
gl.fog_image_format = GL_ALPHA;
}
}
GLint ranges[2];
GLint precision;
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, ranges, &precision);
gl.highp_float_supported = (ranges[0] != 0 || ranges[1] != 0) && precision != 0;
}
struct ShaderUniforms_t ShaderUniforms;
@ -639,14 +653,16 @@ bool CompilePipelineShader( PipelineShader* s)
{
char vshader[8192];
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud);
int rc = sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud);
verify(rc + 1 <= sizeof(vshader));
char pshader[8192];
sprintf(pshader,PixelPipelineShader, gl.glsl_version_header, gl.gl_version,
rc = sprintf(pshader,PixelPipelineShader, gl.glsl_version_header, gl.gl_version,
s->cp_AlphaTest,s->pp_ClipTestMode,s->pp_UseAlpha,
s->pp_Texture,s->pp_IgnoreTexA,s->pp_ShadInstr,s->pp_Offset,s->pp_FogCtrl, s->pp_Gouraud, s->pp_BumpMap,
s->fog_clamping, s->trilinear);
verify(rc + 1 <= sizeof(pshader));
s->program=gl_CompileAndLink(vshader, pshader);
@ -658,7 +674,6 @@ bool CompilePipelineShader( PipelineShader* s)
//get the uniform locations
s->depth_scale = glGetUniformLocation(s->program, "depth_scale");
s->extra_depth_scale = glGetUniformLocation(s->program, "extra_depth_scale");
s->pp_ClipTest = glGetUniformLocation(s->program, "pp_ClipTest");
@ -863,14 +878,14 @@ void UpdateFogTexture(u8 *fog_table, GLenum texture_slot, GLint fog_image_format
if (fogTextureId == 0)
{
fogTextureId = glcache.GenTexture();
glcache.BindTexture(GL_TEXTURE_2D, fogTextureId);
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, fogTextureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else
glcache.BindTexture(GL_TEXTURE_2D, fogTextureId);
glBindTexture(GL_TEXTURE_2D, fogTextureId);
u8 temp_tex_buffer[256];
MakeFogTexture(temp_tex_buffer);
@ -1023,8 +1038,6 @@ bool RenderFrame()
ShaderUniforms.depth_coefs[2] = 0;
ShaderUniforms.depth_coefs[3] = 0;
ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale;
//VERT and RAM fog color constants
u8* fog_colvert_bgra = (u8*)&FOG_COL_VERT;
u8* fog_colram_bgra = (u8*)&FOG_COL_RAM;
@ -1040,7 +1053,7 @@ bool RenderFrame()
u8* fog_density = (u8*)&FOG_DENSITY;
float fog_den_mant = fog_density[1] / 128.0f; //bit 7 -> x. bit, so [6:0] -> fraction -> /128
s32 fog_den_exp = (s8)fog_density[0];
ShaderUniforms.fog_den_float = fog_den_mant * powf(2.0f, fog_den_exp);
ShaderUniforms.fog_den_float = fog_den_mant * powf(2.0f, fog_den_exp) * settings.rend.ExtraDepthScale;
ShaderUniforms.fog_clamp_min[0] = ((pvrrc.fog_clamp_min >> 16) & 0xFF) / 255.0f;
ShaderUniforms.fog_clamp_min[1] = ((pvrrc.fog_clamp_min >> 8) & 0xFF) / 255.0f;
@ -1065,7 +1078,7 @@ bool RenderFrame()
ShaderUniforms.PT_ALPHA=(PT_ALPHA_REF&0xFF)/255.0f;
for (auto& it : gl.shaders)
for (const auto& it : gl.shaders)
{
glcache.UseProgram(it.second.program);
ShaderUniforms.Set(&it.second);

View File

@ -30,7 +30,6 @@ struct PipelineShader
GLuint program;
GLuint depth_scale;
GLuint extra_depth_scale;
GLuint pp_ClipTest,cp_AlphaTestValue;
GLuint sp_FOG_COL_RAM,sp_FOG_COL_VERT,sp_FOG_DENSITY;
GLuint trilinear_alpha;
@ -101,6 +100,7 @@ struct gl_ctx
GLenum index_type;
bool GL_OES_packed_depth_stencil_supported;
bool GL_OES_depth24_supported;
bool highp_float_supported;
size_t get_index_size() { return index_type == GL_UNSIGNED_INT ? sizeof(u32) : sizeof(u16); }
};
@ -159,7 +159,6 @@ extern struct ShaderUniforms_t
{
float PT_ALPHA;
float depth_coefs[4];
float extra_depth_scale;
float fog_den_float;
float ps_FOG_COL_RAM[3];
float ps_FOG_COL_VERT[3];
@ -168,7 +167,7 @@ extern struct ShaderUniforms_t
float fog_clamp_max[4];
glm::mat4 normal_mat;
void Set(PipelineShader* s)
void Set(const PipelineShader* s)
{
if (s->cp_AlphaTestValue!=-1)
glUniform1f(s->cp_AlphaTestValue,PT_ALPHA);
@ -176,9 +175,6 @@ extern struct ShaderUniforms_t
if (s->depth_scale!=-1)
glUniform4fv( s->depth_scale, 1, depth_coefs);
if (s->extra_depth_scale != -1)
glUniform1f(s->extra_depth_scale, extra_depth_scale);
if (s->sp_FOG_DENSITY!=-1)
glUniform1f( s->sp_FOG_DENSITY,fog_den_float);

View File

@ -55,24 +55,23 @@ protected:
T MakeFragmentUniforms()
{
T fragUniforms;
fragUniforms.extra_depth_scale = settings.rend.ExtraDepthScale;
//VERT and RAM fog color constants
u8* fog_colvert_bgra=(u8*)&FOG_COL_VERT;
u8* fog_colram_bgra=(u8*)&FOG_COL_RAM;
fragUniforms.sp_FOG_COL_VERT[0]=fog_colvert_bgra[2]/255.0f;
fragUniforms.sp_FOG_COL_VERT[1]=fog_colvert_bgra[1]/255.0f;
fragUniforms.sp_FOG_COL_VERT[2]=fog_colvert_bgra[0]/255.0f;
u8* fog_colvert_bgra = (u8*)&FOG_COL_VERT;
u8* fog_colram_bgra = (u8*)&FOG_COL_RAM;
fragUniforms.sp_FOG_COL_VERT[0] = fog_colvert_bgra[2] / 255.0f;
fragUniforms.sp_FOG_COL_VERT[1] = fog_colvert_bgra[1] / 255.0f;
fragUniforms.sp_FOG_COL_VERT[2] = fog_colvert_bgra[0] / 255.0f;
fragUniforms.sp_FOG_COL_RAM[0]=fog_colram_bgra [2]/255.0f;
fragUniforms.sp_FOG_COL_RAM[1]=fog_colram_bgra [1]/255.0f;
fragUniforms.sp_FOG_COL_RAM[2]=fog_colram_bgra [0]/255.0f;
fragUniforms.sp_FOG_COL_RAM[0] = fog_colram_bgra[2] / 255.0f;
fragUniforms.sp_FOG_COL_RAM[1] = fog_colram_bgra[1] / 255.0f;
fragUniforms.sp_FOG_COL_RAM[2] = fog_colram_bgra[0] / 255.0f;
//Fog density constant
u8* fog_density=(u8*)&FOG_DENSITY;
float fog_den_mant=fog_density[1]/128.0f; //bit 7 -> x. bit, so [6:0] -> fraction -> /128
s32 fog_den_exp=(s8)fog_density[0];
fragUniforms.sp_FOG_DENSITY = fog_den_mant * powf(2.0f, fog_den_exp);
u8* fog_density = (u8*)&FOG_DENSITY;
float fog_den_mant = fog_density[1] / 128.0f; //bit 7 -> x. bit, so [6:0] -> fraction -> /128
s32 fog_den_exp = (s8)fog_density[0];
fragUniforms.sp_FOG_DENSITY = fog_den_mant * powf(2.0f, fog_den_exp) * settings.rend.ExtraDepthScale;
fragUniforms.colorClampMin[0] = ((pvrrc.fog_clamp_min >> 16) & 0xFF) / 255.0f;
fragUniforms.colorClampMin[1] = ((pvrrc.fog_clamp_min >> 8) & 0xFF) / 255.0f;

View File

@ -46,7 +46,6 @@ public:
float sp_FOG_COL_VERT[4]; // same comment
float cp_AlphaTestValue;
float sp_FOG_DENSITY;
float extra_depth_scale;
float shade_scale_factor; // new for OIT
};

View File

@ -85,7 +85,6 @@ layout (std140, set = 0, binding = 1) uniform FragmentShaderUniforms
vec4 sp_FOG_COL_VERT;
float cp_AlphaTestValue;
float sp_FOG_DENSITY;
float extra_depth_scale;
float shade_scale_factor;
} uniformBuffer;
@ -312,7 +311,7 @@ layout (set = 0, binding = 2) uniform sampler2D fog_table;
float fog_mode2(float w)
{
float z = clamp(w * uniformBuffer.extra_depth_scale * uniformBuffer.sp_FOG_DENSITY, 1.0, 255.9999);
float z = clamp(w * uniformBuffer.sp_FOG_DENSITY, 1.0, 255.9999);
float exp = floor(log2(z));
float m = z * 16.0 / pow(2.0, exp) - 16.0;
float idx = floor(m) + exp * 16.0 + 0.5;

View File

@ -104,7 +104,6 @@ layout (std140, set = 0, binding = 1) uniform FragmentShaderUniforms
vec4 sp_FOG_COL_VERT;
float cp_AlphaTestValue;
float sp_FOG_DENSITY;
float extra_depth_scale;
} uniformBuffer;
layout (push_constant) uniform pushBlock
@ -127,7 +126,7 @@ layout (set = 0, binding = 2) uniform sampler2D fog_table;
float fog_mode2(float w)
{
float z = clamp(w * uniformBuffer.extra_depth_scale * uniformBuffer.sp_FOG_DENSITY, 1.0, 255.9999);
float z = clamp(w * uniformBuffer.sp_FOG_DENSITY, 1.0, 255.9999);
float exp = floor(log2(z));
float m = z * 16.0 / pow(2.0, exp) - 16.0;
float idx = floor(m) + exp * 16.0 + 0.5;

View File

@ -70,7 +70,6 @@ struct FragmentShaderUniforms
float sp_FOG_COL_VERT[4]; // same comment
float cp_AlphaTestValue;
float sp_FOG_DENSITY;
float extra_depth_scale;
};
class ShaderManager