diff --git a/Quake/gl_draw.c b/Quake/gl_draw.c index 48a9b0a5a..82b77101f 100644 --- a/Quake/gl_draw.c +++ b/Quake/gl_draw.c @@ -951,13 +951,31 @@ Draw_FadeScreen -- johnfitz -- revised void Draw_FadeScreen (void) { guivertex_t *verts; + int type; float smax = 0.f, tmax = 0.f, s; if (scr_menubgalpha.value <= 0.f) return; + if (scr_menubgstyle.value < 0.f) + { + if (softemu >= SOFTEMU_BANDED) + type = MENUBG_DOSQUAKE; + else if (softemu == SOFTEMU_COARSE) + type = MENUBG_WINQUAKE_SCALED; + else if (softemu == SOFTEMU_FINE) + type = MENUBG_WINQUAKE; + else + type = MENUBG_GLQUAKE; + } + else + { + type = (int)scr_menubgstyle.value; + type = CLAMP (0, type, MENUBG_NUMTYPES - 1); + } + GL_SetCanvas (CANVAS_DEFAULT); - if (softemu >= SOFTEMU_BANDED) + if (type == MENUBG_DOSQUAKE) { float clr[3]; Draw_SetTexture (whitetexture); @@ -979,11 +997,16 @@ void Draw_FadeScreen (void) s = (sqrt (s) + s) * 0.5f; // ~0.6 with scr_menubgalpha 0.5 GL_SetCanvasColor (0.095f, 0.08f, 0.045f, s); } - else if (softemu == SOFTEMU_COARSE) + else if (type == MENUBG_WINQUAKE || type == MENUBG_WINQUAKE_SCALED) { - s = q_min ((float)vid.guiwidth / 320.0f, (float)vid.guiheight / 200.0f); - s = CLAMP (1.0f, scr_menuscale.value, s); - s = floor (s); + if (type == MENUBG_WINQUAKE_SCALED) + { + s = q_min ((float)vid.guiwidth / 320.0f, (float)vid.guiheight / 200.0f); + s = CLAMP (1.0f, scr_menuscale.value, s); + s = floor (s); + } + else + s = 1.f; smax = glwidth / (winquakemenubg->width * s); tmax = glheight / (winquakemenubg->height * s); Draw_SetTexture (winquakemenubg); @@ -1000,7 +1023,7 @@ void Draw_FadeScreen (void) GL_SetCanvasColor (0.f, 0.f, 0.f, s); } } - else + else // MENUBG_GLQUAKE { Draw_SetTexture (whitetexture); Draw_SetBlending (GLS_BLEND_ALPHA); diff --git a/Quake/gl_rmain.c b/Quake/gl_rmain.c index 40a3b9215..a829883e4 100644 --- a/Quake/gl_rmain.c +++ b/Quake/gl_rmain.c @@ -111,6 +111,9 @@ cvar_t r_noshadow_list = {"r_noshadow_list", "progs/flame2.mdl,progs/flame.mdl,p extern cvar_t r_vfog; extern cvar_t vid_fsaa; //johnfitz +extern cvar_t r_softemu_dither; +extern cvar_t r_softemu_dither_screen; +extern cvar_t r_softemu_dither_texture; cvar_t gl_zfix = {"gl_zfix", "1", CVAR_ARCHIVE}; // QuakeSpasm z-fighting fix @@ -311,6 +314,8 @@ void GL_DeleteFrameBuffers (void) // //============================================================================== +static const float NOISESCALE = 9.f / 255.f; + extern GLuint gl_palette_lut; extern GLuint gl_palette_buffer[2]; @@ -322,12 +327,14 @@ GL_PostProcess void GL_PostProcess (void) { int palidx, variant; + float dither; if (!GL_NeedsPostprocess ()) return; GL_BeginGroup ("Postprocess"); palidx = GLPalette_Postprocess (); + dither = (softemu == SOFTEMU_FINE) ? NOISESCALE * r_softemu_dither.value * r_softemu_dither_screen.value : 0.f; GL_BindFramebufferFunc (GL_FRAMEBUFFER, 0); glViewport (glx, gly, glwidth, glheight); @@ -339,7 +346,7 @@ void GL_PostProcess (void) GL_BindNative (GL_TEXTURE1, GL_TEXTURE_3D, gl_palette_lut); GL_BindBufferRange (GL_SHADER_STORAGE_BUFFER, 0, gl_palette_buffer[palidx], 0, 256 * sizeof (GLuint)); if (variant != 2) // some AMD drivers optimize out the uniform in variant #2 - GL_Uniform3fFunc (0, vid_gamma.value, q_min(2.0f, q_max(1.0f, vid_contrast.value)), 1.f/r_refdef.scale); + GL_Uniform4fFunc (0, vid_gamma.value, q_min(2.0f, q_max(1.0f, vid_contrast.value)), 1.f/r_refdef.scale, dither); glDrawArrays (GL_TRIANGLES, 0, 3); @@ -923,6 +930,16 @@ void R_SetupView (void) r_framedata.eyepos[1] = r_refdef.vieworg[1]; r_framedata.eyepos[2] = r_refdef.vieworg[2]; r_framedata.time = cl.time; + if (softemu == SOFTEMU_FINE || softemu == SOFTEMU_COARSE) + { + r_framedata.screendither = NOISESCALE * r_softemu_dither.value * r_softemu_dither_screen.value; + r_framedata.texturedither = NOISESCALE * r_softemu_dither.value * r_softemu_dither_texture.value; + } + else + { + r_framedata.screendither = 0.f; + r_framedata.texturedither = 0.f; + } Fog_SetupFrame (); //johnfitz Sky_SetupFrame (); diff --git a/Quake/gl_screen.c b/Quake/gl_screen.c index 2c17f09ea..d39fa629d 100644 --- a/Quake/gl_screen.c +++ b/Quake/gl_screen.c @@ -81,6 +81,7 @@ float scr_conlines; // lines of console to display //johnfitz -- new cvars cvar_t scr_menuscale = {"scr_menuscale", "1", CVAR_ARCHIVE}; cvar_t scr_menubgalpha = {"scr_menubgalpha", "0.7", CVAR_ARCHIVE}; +cvar_t scr_menubgstyle = {"scr_menubgstyle", "-1", CVAR_ARCHIVE}; cvar_t scr_sbarscale = {"scr_sbarscale", "1", CVAR_ARCHIVE}; cvar_t scr_sbaralpha = {"scr_sbaralpha", "0.75", CVAR_ARCHIVE}; cvar_t scr_conwidth = {"scr_conwidth", "0", CVAR_ARCHIVE}; @@ -541,6 +542,7 @@ void SCR_Init (void) //johnfitz -- new cvars Cvar_RegisterVariable (&scr_menuscale); Cvar_RegisterVariable (&scr_menubgalpha); + Cvar_RegisterVariable (&scr_menubgstyle); Cvar_RegisterVariable (&scr_sbarscale); Cvar_SetCallback (&scr_sbaralpha, SCR_Callback_refdef); Cvar_RegisterVariable (&scr_sbaralpha); diff --git a/Quake/gl_shaders.h b/Quake/gl_shaders.h index 1c472fafe..c27e0c567 100644 --- a/Quake/gl_shaders.h +++ b/Quake/gl_shaders.h @@ -225,7 +225,6 @@ SOFTWARE.*/\ "#define DITHER_NOISE(uv) tri(bayer01(ivec2(uv)))\n"\ "#define SCREEN_SPACE_NOISE() DITHER_NOISE(floor(gl_FragCoord.xy)+0.5)\n"\ "#define SUPPRESS_BANDING() (bayer(ivec2(gl_FragCoord.xy)) * (1./255.))\n"\ -"#define PAL_NOISESCALE (9./255.)\n"\ //////////////////////////////////////////////////////////////// @@ -245,7 +244,7 @@ static const char postprocess_fragment_shader[] = PALETTE_BUFFER NOISE_FUNCTIONS "\n" -"layout(location=0) uniform vec3 Params;\n" +"layout(location=0) uniform vec4 Params;\n" "\n" "layout(location=0) out vec4 out_fragcolor;\n" "\n" @@ -254,11 +253,12 @@ NOISE_FUNCTIONS " float gamma = Params.x;\n" " float contrast = Params.y;\n" " float scale = Params.z;\n" +" float dither = Params.w;\n" " out_fragcolor = texelFetch(GammaTexture, ivec2(gl_FragCoord), 0);\n" "#if PALETTIZE == 1\n" " vec2 noiseuv = floor(gl_FragCoord.xy * scale) + 0.5;\n" " out_fragcolor.rgb = sqrt(out_fragcolor.rgb);\n" -" out_fragcolor.rgb += DITHER_NOISE(noiseuv) * PAL_NOISESCALE;\n" +" out_fragcolor.rgb += DITHER_NOISE(noiseuv) * dither;\n" " out_fragcolor.rgb *= out_fragcolor.rgb;\n" "#endif // PALETTIZE == 1\n" "#if PALETTIZE\n" @@ -285,6 +285,8 @@ NOISE_FUNCTIONS " vec4 SkyFog;\n"\ " vec3 WindDir;\n"\ " float WindPhase;\n"\ +" float ScreenDither;\n"\ +" float TextureDither;\n"\ " vec3 EyePos;\n"\ " float Time;\n"\ " float ZLogScale;\n"\ @@ -720,9 +722,9 @@ OIT_OUTPUT (out_fragcolor) " farblend *= farblend;\n" " out_fragcolor.rgb = sqrt(out_fragcolor.rgb);\n" " float luma = dot(out_fragcolor.rgb, vec3(.25, .625, .125));\n" -" float nearnoise = tri(whitenoise01(lmuv * lmsize)) * luma;\n" -" float farnoise = Fog.w > 0. ? SCREEN_SPACE_NOISE() : 0.;\n" -" out_fragcolor.rgb += mix(nearnoise, farnoise, farblend) * PAL_NOISESCALE;\n" +" float nearnoise = tri(whitenoise01(lmuv * lmsize)) * luma * TextureDither;\n" +" float farnoise = Fog.w > 0. ? SCREEN_SPACE_NOISE() * ScreenDither : 0.;\n" +" out_fragcolor.rgb += mix(nearnoise, farnoise, farblend);\n" " out_fragcolor.rgb *= out_fragcolor.rgb;\n" "#endif // DITHER == 1\n" "#if DITHER >= 2\n" @@ -803,7 +805,7 @@ OIT_OUTPUT (out_fragcolor) " if (Fog.w > 0.)\n" " {\n" " out_fragcolor.rgb = sqrt(out_fragcolor.rgb);\n" -" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * PAL_NOISESCALE;\n" +" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * ScreenDither;\n" " out_fragcolor.rgb *= out_fragcolor.rgb;\n" " }\n" "#else\n" @@ -961,7 +963,7 @@ NOISE_FUNCTIONS " out_fragcolor.rgb = mix(out_fragcolor.rgb, SkyFog.rgb, SkyFog.a);\n" "#if DITHER\n" " out_fragcolor.rgb = sqrt(out_fragcolor.rgb);\n" -" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * PAL_NOISESCALE;\n" +" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * ScreenDither;\n" " out_fragcolor.rgb *= out_fragcolor.rgb;\n" "#else\n" " out_fragcolor.rgb += SUPPRESS_BANDING();\n" @@ -1000,6 +1002,7 @@ static const char sky_boxside_fragment_shader[] = NOISE_FUNCTIONS "\n" "layout(location=2) uniform vec4 Fog;\n" +"layout(location=3) uniform float ScreenDither;\n" "\n" "layout(location=0) in vec3 in_dir;\n" "layout(location=1) in vec2 in_uv;\n" @@ -1012,7 +1015,7 @@ NOISE_FUNCTIONS " out_fragcolor.rgb = mix(out_fragcolor.rgb, Fog.rgb, Fog.w);\n" "#if DITHER\n" " out_fragcolor.rgb = sqrt(out_fragcolor.rgb);\n" -" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * PAL_NOISESCALE;\n" +" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * ScreenDither;\n" " out_fragcolor.rgb *= out_fragcolor.rgb;\n" "#else\n" " out_fragcolor.rgb += SUPPRESS_BANDING();\n" @@ -1041,6 +1044,7 @@ NOISE_FUNCTIONS " mat4 ViewProj;\n"\ " vec3 EyePos;\n"\ " vec4 Fog;\n"\ +" float ScreenDither;\n"\ " InstanceData instances[];\n"\ "};\n"\ @@ -1185,7 +1189,7 @@ OIT_OUTPUT (out_fragcolor) " if (abs(Fog.w) > 0.)\n" " {\n" " out_fragcolor.rgb = sqrt(out_fragcolor.rgb);\n" -" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * PAL_NOISESCALE;\n" +" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * ScreenDither;\n" " out_fragcolor.rgb *= out_fragcolor.rgb;\n" " }\n" "#else\n" @@ -1239,7 +1243,7 @@ NOISE_FUNCTIONS " if (Fog.w > 0.)\n" " {\n" " out_fragcolor.rgb = sqrt(out_fragcolor.rgb);\n" -" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * PAL_NOISESCALE;\n" +" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * ScreenDither;\n" " out_fragcolor.rgb *= out_fragcolor.rgb;\n" " }\n" "#else\n" @@ -1313,7 +1317,7 @@ OIT_OUTPUT (out_fragcolor) " if (Fog.w > 0.)\n" " {\n" " out_fragcolor.rgb = sqrt(out_fragcolor.rgb);\n" -" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * PAL_NOISESCALE;\n" +" out_fragcolor.rgb += SCREEN_SPACE_NOISE() * ScreenDither;\n" " out_fragcolor.rgb *= out_fragcolor.rgb;\n" " }\n" "#else\n" diff --git a/Quake/gl_sky.c b/Quake/gl_sky.c index 7a5e5d39d..a83404a50 100644 --- a/Quake/gl_sky.c +++ b/Quake/gl_sky.c @@ -724,6 +724,7 @@ void Sky_DrawSkyBox (void) GL_UniformMatrix4fvFunc (0, 1, GL_FALSE, r_matviewproj); GL_Uniform3fvFunc (1, 1, r_refdef.vieworg); GL_Uniform4fvFunc (2, 1, fog); + GL_Uniform1fFunc (3, r_framedata.screendither); for (i = 0; i < 6; i++) { diff --git a/Quake/gl_texmgr.c b/Quake/gl_texmgr.c index 7ea85f941..b5baf251e 100644 --- a/Quake/gl_texmgr.c +++ b/Quake/gl_texmgr.c @@ -39,6 +39,12 @@ static const struct { cvar_t r_softemu = {"r_softemu", "0", CVAR_ARCHIVE}; cvar_t r_softemu_metric = {"r_softemu_metric", "-1", CVAR_ARCHIVE}; +cvar_t r_softemu_lightmap_banding = {"r_softemu_lightmap_banding", "-1", CVAR_ARCHIVE}; +cvar_t r_softemu_mdl_warp = {"r_softemu_mdl_warp", "-1", CVAR_ARCHIVE}; +cvar_t r_softemu_dither = {"r_softemu_dither", "1.0", CVAR_ARCHIVE}; +cvar_t r_softemu_dither_screen = {"r_softemu_dither_screen", "1.0", CVAR_ARCHIVE}; +cvar_t r_softemu_dither_texture = {"r_softemu_dither_texture", "1.0", CVAR_ARCHIVE}; + static cvar_t gl_max_size = {"gl_max_size", "0", CVAR_NONE}; static cvar_t gl_picmip = {"gl_picmip", "0", CVAR_NONE}; cvar_t gl_lodbias = {"gl_lodbias", "auto", CVAR_ARCHIVE }; @@ -333,8 +339,8 @@ void TexMgr_ApplySettings (void) gl_texfilter.anisotropy = CLAMP (1.f, gl_texture_anisotropy.value, gl_max_anisotropy); gl_texfilter.lodbias = lodbias; - // softemu 2 & 3 override filtering mode, unless it's GL_NEAREST - if (softemu >= SOFTEMU_COARSE && gl_texfilter.mode != 0) + // if softemu is either 2 & 3 or r_softemu_lightmap_banding is > 0 we override the filtering mode, unless it's GL_NEAREST + if (gl_texfilter.mode != 0 && (softemu >= SOFTEMU_COARSE || r_softemu_lightmap_banding.value > 0.f)) { const float SOFTEMU_ANISOTROPY = 8.f; gl_texfilter.mode = 2; // nearest with linear mips @@ -867,6 +873,12 @@ void TexMgr_Init (void) Cvar_SetCallback (&gl_lodbias, TexMgr_LodBias_f); Cvar_RegisterVariable (&r_softemu); Cvar_SetCallback (&r_softemu, TexMgr_SoftEmu_f); + Cvar_RegisterVariable (&r_softemu_lightmap_banding); + Cvar_SetCallback (&r_softemu_lightmap_banding, TexMgr_SoftEmu_f); + Cvar_RegisterVariable (&r_softemu_mdl_warp); + Cvar_RegisterVariable (&r_softemu_dither); + Cvar_RegisterVariable (&r_softemu_dither_screen); + Cvar_RegisterVariable (&r_softemu_dither_texture); Cmd_AddCommand ("gl_describetexturemodes", &TexMgr_DescribeTextureModes_f); cmd = Cmd_AddCommand ("imagelist", &TexMgr_Imagelist_f); if (cmd) diff --git a/Quake/glquake.h b/Quake/glquake.h index 170de18b7..aa41adbcb 100644 --- a/Quake/glquake.h +++ b/Quake/glquake.h @@ -403,12 +403,15 @@ typedef struct gpuframedata_s { float skyfogdata[4]; vec3_t winddir; float windphase; + float screendither; + float texturedither; + float _padding1[2]; vec3_t eyepos; float time; float zlogscale; float zlogbias; int numlights; - int padding; + int _padding2; } gpuframedata_t; extern gpulightbuffer_t r_lightbuffer; @@ -500,7 +503,7 @@ typedef struct glprogs_s { GLuint oit_resolve[2]; // [msaa] /* 3d */ - GLuint world[2][3][3]; // [OIT][dither][mode:solid/alpha test/water] + GLuint world[2][3][3]; // [OIT][standard/dithered/banded][solid/alpha test/water] GLuint water[2][2]; // [OIT][dither] GLuint skystencil; GLuint skylayers[2]; // [dither] diff --git a/Quake/r_alias.c b/Quake/r_alias.c index 210f89ce8..ec3fb2135 100644 --- a/Quake/r_alias.c +++ b/Quake/r_alias.c @@ -71,6 +71,8 @@ struct ibuf_s { vec3_t eyepos; float _pad; vec4_t fog; + float dither; + float _padding[3]; } global; aliasinstance_t inst[MAX_ALIAS_INSTANCES]; } ibuf; @@ -292,10 +294,11 @@ R_FlushAliasInstances */ void R_FlushAliasInstances (void) { + extern cvar_t r_softemu_mdl_warp; qmodel_t *model; aliashdr_t *paliashdr; qboolean alphatest, translucent, oit, md5; - GLuint program; + int mode; unsigned state; GLuint buf; GLbyte *ofs; @@ -320,16 +323,16 @@ void R_FlushAliasInstances (void) switch (softemu) { case SOFTEMU_BANDED: - program = glprogs.alias[oit][ALIASSHADER_NOPERSP][alphatest][md5]; + mode = r_softemu_mdl_warp.value != 0.f ? ALIASSHADER_NOPERSP : ALIASSHADER_STANDARD; break; case SOFTEMU_COARSE: - program = glprogs.alias[oit][ALIASSHADER_DITHER][alphatest][md5]; + mode = r_softemu_mdl_warp.value > 0.f ? ALIASSHADER_NOPERSP : ALIASSHADER_DITHER; break; default: - program = glprogs.alias[oit][ALIASSHADER_STANDARD][alphatest][md5]; + mode = r_softemu_mdl_warp.value > 0.f ? ALIASSHADER_NOPERSP : ALIASSHADER_STANDARD; break; } - GL_UseProgram (program); + GL_UseProgram (glprogs.alias[oit][mode][alphatest][md5]); if (md5) state = GLS_CULL_BACK | GLS_ATTRIBS(5); @@ -351,6 +354,7 @@ void R_FlushAliasInstances (void) -fabs (r_framedata.fogdata[3]) : fabs (r_framedata.fogdata[3]) ; + ibuf.global.dither = r_framedata.screendither; ibuf_size = sizeof(ibuf.global) + sizeof(ibuf.inst[0]) * ibuf.count; GL_Upload (GL_SHADER_STORAGE_BUFFER, &ibuf.global, ibuf_size, &buf, &ofs); diff --git a/Quake/r_world.c b/Quake/r_world.c index 35076715d..5c8b5cb10 100644 --- a/Quake/r_world.c +++ b/Quake/r_world.c @@ -342,6 +342,37 @@ static void R_AddBModelCall (int index, int first_instance, int num_instances, t ++num_bmodel_calls; } +/* +============= +R_ChooseBModelProgram +============= +*/ +static GLuint R_ChooseBModelProgram (qboolean oit, qboolean alphatest) +{ + extern cvar_t r_softemu_lightmap_banding; + + switch (softemu) + { + case SOFTEMU_BANDED: + if (r_softemu_lightmap_banding.value != 0.f) + return glprogs.world[oit][2][alphatest]; + else + return glprogs.world[oit][1][alphatest]; + + case SOFTEMU_COARSE: + if (r_softemu_lightmap_banding.value > 0.f) + return glprogs.world[oit][2][alphatest]; + else + return glprogs.world[oit][1][alphatest]; + + default: + if (r_softemu_lightmap_banding.value > 0.f) + return glprogs.world[oit][2][alphatest]; + else + return glprogs.world[oit][0][alphatest]; + } +} + typedef enum { BP_SOLID, BP_ALPHATEST, @@ -383,12 +414,12 @@ static void R_DrawBrushModels_Real (entity_t **ents, int count, brushpass_t pass case BP_SOLID: texbegin = 0; texend = TEXTYPE_CUTOUT; - program = glprogs.world[oit][q_max(0, (int)softemu - 1)][WORLDSHADER_SOLID]; + program = R_ChooseBModelProgram (oit, false); break; case BP_ALPHATEST: texbegin = TEXTYPE_CUTOUT; texend = TEXTYPE_CUTOUT + 1; - program = glprogs.world[oit][q_max(0, (int)softemu - 1)][WORLDSHADER_ALPHATEST]; + program = R_ChooseBModelProgram (oit, true); break; case BP_SKYLAYERS: texbegin = TEXTYPE_SKY; diff --git a/Quake/screen.h b/Quake/screen.h index b17d9e5b0..6e4c3570a 100644 --- a/Quake/screen.h +++ b/Quake/screen.h @@ -85,8 +85,19 @@ typedef struct glcanvas_s { extern glcanvas_t glcanvas; +typedef enum menubg_t +{ + MENUBG_GLQUAKE, + MENUBG_WINQUAKE, + MENUBG_WINQUAKE_SCALED, + MENUBG_DOSQUAKE, + + MENUBG_NUMTYPES, +} menubgstyle_t; + extern cvar_t scr_menuscale; extern cvar_t scr_menubgalpha; +extern cvar_t scr_menubgstyle; extern cvar_t scr_sbarscale; extern cvar_t scr_conwidth; extern cvar_t scr_conscale;