Port Saturn's Light dither shader for OGL

This commit is contained in:
NepDisk 2026-04-28 14:26:47 -04:00
parent dc5f42cdaf
commit e6b1826d3e
5 changed files with 84 additions and 19 deletions

View file

@ -914,10 +914,13 @@ consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL);
CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}}; CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}};
void CV_glpaletterendering_OnChange(void); void CV_glpaletterendering_OnChange(void);
void CV_glpalettedepth_OnChange(void); void CV_glpalettedepth_OnChange(void);
void CV_gllightdithering_OnChange(void);
consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletteshader", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_glpaletterendering_OnChange); consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletteshader", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_glpaletterendering_OnChange);
consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange); consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange);
consvar_t cv_gllightdither = CVAR_INIT ("gr_lightdithering", "Off", CV_CALL|CV_SAVE, CV_OnOff, CV_gllightdithering_OnChange);
// Isolates rendering to one of the top level portals. // Isolates rendering to one of the top level portals.
// (Stencil cutting of the portal is also disabled) // (Stencil cutting of the portal is also disabled)
// Use gr_printportals to find the number to use. // Use gr_printportals to find the number to use.
@ -958,7 +961,15 @@ void CV_glpaletterendering_OnChange(void)
} }
} }
void CV_glpalettedepth_OnChange(void); void CV_gllightdithering_OnChange(void)
{
ONLY_IF_GL_LOADED
if (gl_shadersavailable)
{
HWR_CompileShaders();
}
}
void CV_glpalettedepth_OnChange(void) void CV_glpalettedepth_OnChange(void)
{ {
ONLY_IF_GL_LOADED ONLY_IF_GL_LOADED
@ -1024,6 +1035,8 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_glpaletterendering); CV_RegisterVar(&cv_glpaletterendering);
CV_RegisterVar(&cv_glpalettedepth); CV_RegisterVar(&cv_glpalettedepth);
CV_RegisterVar(&cv_gllightdither);
COM_AddCommand("gr_printportals", Command_Glprintportals_f); COM_AddCommand("gr_printportals", Command_Glprintportals_f);
CV_RegisterVar(&cv_gldebugportal); CV_RegisterVar(&cv_gldebugportal);

View file

@ -113,6 +113,7 @@ extern consvar_t cv_glsolvetjoin, cv_glpolytile, cv_glpolyshape;
extern consvar_t cv_glbatching; extern consvar_t cv_glbatching;
extern consvar_t cv_glpaletterendering; extern consvar_t cv_glpaletterendering;
extern consvar_t cv_glpalettedepth; extern consvar_t cv_glpalettedepth;
extern consvar_t cv_gllightdither;
extern consvar_t cv_gldebugportal; extern consvar_t cv_gldebugportal;
extern consvar_t cv_glskydebug; extern consvar_t cv_glskydebug;

View file

@ -81,6 +81,7 @@ static shadertarget_t gl_shadertargets[NUMSHADERTARGETS];
#define MODEL_LIGHTING_DEFINE "#define SRB2_MODEL_LIGHTING" #define MODEL_LIGHTING_DEFINE "#define SRB2_MODEL_LIGHTING"
#define PALETTE_RENDERING_DEFINE "#define SRB2_PALETTE_RENDERING" #define PALETTE_RENDERING_DEFINE "#define SRB2_PALETTE_RENDERING"
#define LIGHT_DITHERING_DEFINE "#define SRB2_LIGHT_DITHER"
// Initialize shader variables and the backend's shader system. Load the base shaders. // Initialize shader variables and the backend's shader system. Load the base shaders.
// Returns false if shaders cannot be used. // Returns false if shaders cannot be used.
@ -284,6 +285,9 @@ static char *HWR_PreprocessShader(char *original)
if (cv_glpaletterendering.value) if (cv_glpaletterendering.value)
ADD_TO_LEN(PALETTE_RENDERING_DEFINE) ADD_TO_LEN(PALETTE_RENDERING_DEFINE)
if (cv_gllightdither.value)
ADD_TO_LEN(LIGHT_DITHERING_DEFINE)
#undef ADD_TO_LEN #undef ADD_TO_LEN
#define VERSION_PART "#version " #define VERSION_PART "#version "
@ -329,6 +333,9 @@ static char *HWR_PreprocessShader(char *original)
if (cv_glpaletterendering.value) if (cv_glpaletterendering.value)
WRITE_DEFINE(PALETTE_RENDERING_DEFINE) WRITE_DEFINE(PALETTE_RENDERING_DEFINE)
if (cv_gllightdither.value)
WRITE_DEFINE(LIGHT_DITHERING_DEFINE)
#undef WRITE_DEFINE #undef WRITE_DEFINE
// Write a #line directive, so compiler errors will report line numbers from the // Write a #line directive, so compiler errors will report line numbers from the

View file

@ -76,15 +76,53 @@
// //
// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro. // Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro.
#define GLSL_DOOM_COLORMAP_DITHER \
"float baseValue = max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
"float endResolutionx = scr_resolution.x;\n" \
"float endResolutiony = scr_resolution.y;\n" \
"if (scr_resolution.x > 1280.0) {\n" \
"endResolutionx = scr_resolution.x * 0.5;\n" \
"}\n" \
"if (scr_resolution.y > 720.0) {\n" \
"endResolutiony = scr_resolution.y * 0.5;\n" \
"}\n" \
"float zFactor = clamp((z - 192.0) / (6144.0 - 192.0), 0.0, 1.0);\n" \
"int scaleFactor = int(mix(1.0, 8.0, zFactor));\n" \
"endResolutionx = endResolutionx * scaleFactor;\n" \
"endResolutiony = endResolutiony * scaleFactor;\n" \
"vec2 normalizedPosition = position * vec2(endResolutionx / scr_resolution.x, endResolutiony / scr_resolution.y);\n" \
"int x = int(mod(normalizedPosition.x, 4.0));\n" \
"int y = int(mod(normalizedPosition.y, 4.0));\n" \
"float bayerMatrix[4*4] = float[4*4](\n" \
"0.0, 8.0, 2.0, 10.0,\n" \
"12.0, 4.0, 14.0, 6.0,\n" \
"3.0, 11.0, 1.0, 9.0,\n" \
"15.0, 7.0, 13.0, 5.0\n" \
");\n" \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"float threshold = (1.0 - pow(zFactor, 2.0)) * (bayerMatrix[y*4 + x] / 11.0);\n" \
"#else\n" \
"float threshold = (1.0 - pow(zFactor, 2.0)) * (bayerMatrix[y*4 + x] / 16.0);\n" \
"#endif\n" \
"return mix(baseValue + threshold - 0.5 / 16.0, baseValue, zFactor);\n"
#define GLSL_DOOM_COLORMAP_NODITHER \
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
#define GLSL_DOOM_COLORMAP \ #define GLSL_DOOM_COLORMAP \
"float R_DoomColormap(float light, float z)\n" \ "uniform vec2 scr_resolution;\n" \
"float R_DoomColormap(float light, float z, vec2 position)\n" \
"{\n" \ "{\n" \
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
"float startmap = (15.0 - lightnum) * 4.0;\n" \ "float startmap = (15.0 - lightnum) * 4.0;\n" \
"float scale = 160.0 / (lightz + 1.0);\n" \ "float scale = 160.0 / (lightz + 1.0);\n" \
"float cap = (155.0 - light) * 0.26;\n" \ "float cap = (155.0 - light) * 0.26;\n" \
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \ "#ifdef SRB2_LIGHT_DITHER\n" \
GLSL_DOOM_COLORMAP_DITHER \
"#else\n" \
GLSL_DOOM_COLORMAP_NODITHER \
"#endif\n" \
"}\n" "}\n"
// lighting cap adjustment: // lighting cap adjustment:
// first num (155.0), increase to make it start to go dark sooner // first num (155.0), increase to make it start to go dark sooner
@ -94,7 +132,7 @@
"float R_DoomLightingEquation(float light)\n" \ "float R_DoomLightingEquation(float light)\n" \
"{\n" \ "{\n" \
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ "float colormap = floor(R_DoomColormap(light, z, gl_FragCoord.xy)) + 0.5;\n" \
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
"}\n" "}\n"
@ -157,7 +195,7 @@
#define GLSL_PALETTE_RENDERING \ #define GLSL_PALETTE_RENDERING \
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
"float light_y = clamp(floor(R_DoomColormap(final_lighting, z)), 0.0, 31.0);\n" \ "float light_y = clamp(floor(R_DoomColormap(final_lighting, z, gl_FragCoord.xy)), 0.0, 31.0);\n" \
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \ "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \
"vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \ "vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \
"final_color.a = texel.a * poly_color.a;\n" \ "final_color.a = texel.a * poly_color.a;\n" \

View file

@ -654,6 +654,8 @@ typedef enum
// misc. // misc.
gluniform_leveltime, gluniform_leveltime,
gluniform_scr_resolution,
gluniform_max, gluniform_max,
} gluniform_t; } gluniform_t;
@ -1935,6 +1937,8 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
UNIFORM_1(shader->uniforms[gluniform_leveltime], shader_leveltime, pglUniform1f); UNIFORM_1(shader->uniforms[gluniform_leveltime], shader_leveltime, pglUniform1f);
UNIFORM_2(shader->uniforms[gluniform_scr_resolution], (GLfloat)vid.width, (GLfloat)vid.height, pglUniform2f);
#undef UNIFORM_1 #undef UNIFORM_1
#undef UNIFORM_2 #undef UNIFORM_2
#undef UNIFORM_3 #undef UNIFORM_3
@ -2050,24 +2054,26 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i)
shader->uniforms[gluniform_brightmap] = GETUNI("brightmap"); shader->uniforms[gluniform_brightmap] = GETUNI("brightmap");
// lighting // lighting
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color"); shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color"); shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color"); shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
shader->uniforms[gluniform_lighting] = GETUNI("lighting"); shader->uniforms[gluniform_lighting] = GETUNI("lighting");
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
shader->uniforms[gluniform_newfade] = GETUNI("newfade"); shader->uniforms[gluniform_newfade] = GETUNI("newfade");
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir"); shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast"); shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight"); shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
// palette rendering // palette rendering
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex"); shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex"); shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex"); shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
// misc. (custom shaders) // misc. (custom shaders)
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
#undef GETUNI #undef GETUNI