Only add the lightmode actually being used into the shader

This commit is contained in:
Magnus Norddahl 2023-04-19 02:28:32 +02:00 committed by Christoph Oelckers
parent ca7e5be6b4
commit 85f138841c
14 changed files with 360 additions and 280 deletions

View file

@ -222,6 +222,7 @@ protected:
int mTextureClamp;
int mTextureModeFlags;
int mSoftLight;
int mLightMode = -1;
float mLightParms[4];
float mAlphaThreshold;
@ -459,6 +460,11 @@ public:
mLightParms[3] = -1.f;
}
void SetLightMode(int lightmode)
{
mLightMode = lightmode;
}
void SetGlowPlanes(const FVector4 &tp, const FVector4& bp)
{
mStreamData.uGlowTopPlane = tp;

View file

@ -182,8 +182,8 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
if (key.Detailmap) definesBlock << "#define TEXF_Detailmap\n";
if (key.Glowmap) definesBlock << "#define TEXF_Glowmap\n";
if (key.UseRaytrace) definesBlock << "\n#define USE_RAYTRACE\n";
if (key.UseShadowmap) definesBlock << "\n#define USE_SHADOWMAP\n";
if (key.UseRaytrace) definesBlock << "#define USE_RAYTRACE\n";
if (key.UseShadowmap) definesBlock << "#define USE_SHADOWMAP\n";
switch (key.TextureMode)
{
@ -196,6 +196,20 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
case TM_FOGLAYER: definesBlock << "#define TM_FOGLAYER\n"; break;
}
switch (key.LightMode)
{
case 0: definesBlock << "#define LIGHTMODE_DEFAULT\n"; break;
case 1: definesBlock << "#define LIGHTMODE_SOFTWARE\n"; break;
case 2: definesBlock << "#define LIGHTMODE_VANILLA\n"; break;
case 3: definesBlock << "#define LIGHTMODE_BUILD\n"; break;
}
if (key.FogBeforeLights) definesBlock << "#define FOG_BEFORE_LIGHTS\n";
if (key.FogAfterLights) definesBlock << "#define FOG_AFTER_LIGHTS\n";
if (key.FogRadial) definesBlock << "#define FOG_RADIAL\n";
if (key.SWLightRadial) definesBlock << "#define SWLIGHT_RADIAL\n";
if (key.SWLightBanded) definesBlock << "#define SWLIGHT_BANDED\n";
FString layoutBlock;
layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_shared.glsl").GetChars() << "\n";
layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_frag.glsl").GetChars() << "\n";

View file

@ -76,7 +76,13 @@ public:
uint64_t GBufferPass : 1; // GBUFFER_PASS
uint64_t UseShadowmap : 1; // USE_SHADOWMAPS
uint64_t UseRaytrace : 1; // USE_RAYTRACE
uint64_t Unused : 52;
uint64_t FogBeforeLights : 1; // FOG_BEFORE_LIGHTS
uint64_t FogAfterLights : 1; // FOG_AFTER_LIGHTS
uint64_t FogRadial : 1; // FOG_RADIAL
uint64_t SWLightRadial : 1; // SWLIGHT_RADIAL
uint64_t SWLightBanded : 1; // SWLIGHT_BANDED
uint64_t LightMode : 2; // LIGHTMODE_DEFAULT, LIGHTMODE_SOFTWARE, LIGHTMODE_VANILLA, LIGHTMODE_BUILD
uint64_t Unused : 45;
};
uint64_t AsQWORD = 0;
};

View file

@ -253,7 +253,46 @@ void VkRenderState::ApplyRenderPass(int dt)
pipelineKey.ShaderKey.Brightmap = (uTextureMode & TEXF_Brightmap) != 0;
pipelineKey.ShaderKey.Detailmap = (uTextureMode & TEXF_Detailmap) != 0;
pipelineKey.ShaderKey.Glowmap = (uTextureMode & TEXF_Glowmap) != 0;
pipelineKey.ShaderKey.Simple2D = (mFogEnabled == 2);
// The way GZDoom handles state is just plain insanity!
int fogset = 0;
if (mFogEnabled)
{
if (mFogEnabled == 2)
{
fogset = -3; // 2D rendering with 'foggy' overlay.
}
else if ((mFogColor & 0xffffff) == 0)
{
fogset = gl_fogmode;
}
else
{
fogset = -gl_fogmode;
}
}
pipelineKey.ShaderKey.Simple2D = (fogset == -3);
pipelineKey.ShaderKey.FogBeforeLights = (fogset > 0);
pipelineKey.ShaderKey.FogAfterLights = (fogset < 0);
pipelineKey.ShaderKey.FogRadial = (fogset < -1 || fogset > 1);
pipelineKey.ShaderKey.SWLightRadial = (gl_fogmode == 2);
pipelineKey.ShaderKey.SWLightBanded = false; // gl_bandedswlight;
float lightlevel = mLightParms[3];
if (lightlevel < 0.0)
{
pipelineKey.ShaderKey.LightMode = 0; // Default
}
else
{
if (mLightMode == 5)
pipelineKey.ShaderKey.LightMode = 3; // Build
else if (mLightMode == 16)
pipelineKey.ShaderKey.LightMode = 2; // Vanilla
else
pipelineKey.ShaderKey.LightMode = 1; // Software
}
pipelineKey.ShaderKey.UseShadowmap = gl_light_shadowmap;
pipelineKey.ShaderKey.UseRaytrace = gl_light_raytrace;

View file

@ -482,6 +482,8 @@ void HWDrawInfo::RenderScene(FRenderState &state)
const auto &vp = Viewpoint;
RenderAll.Clock();
state.SetLightMode((int)lightmode);
state.SetDepthMask(true);
state.EnableFog(true);

View file

@ -6,49 +6,13 @@ void main()
#endif
Material material = CreateMaterial();
vec4 frag = material.Base;
#ifndef NO_ALPHATEST
if (frag.a <= uAlphaThreshold) discard;
if (material.Base.a <= uAlphaThreshold) discard;
#endif
#ifdef SIMPLE2D // uses the fog color to add a color overlay
#ifdef TM_FOGLAYER
float gray = grayscale(frag);
vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2;
frag = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a);
frag *= vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
#else
frag *= vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
#endif
#else
#ifdef TM_FOGLAYER
float fogdist = 0.0;
float fogfactor = 0.0;
FragColor = ProcessLightMode(material);
// calculate fog factor
if (uFogEnabled != 0)
{
if (uFogEnabled == 1 || uFogEnabled == -1)
{
fogdist = max(16.0, pixelpos.w);
}
else
{
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
}
fogfactor = exp2 (uFogDensity * fogdist);
}
frag = vec4(uFogColor.rgb, (1.0 - fogfactor) * frag.a * 0.75 * vColor.a);
#else
frag = getLightColor(material);
#endif
#endif
FragColor = frag;
#ifdef GBUFFER_PASS
FragFog = vec4(AmbientOcclusionColor(), 1.0);
FragNormal = vec4(vEyeNormal.xyz * 0.5 + 0.5, 1.0);

View file

@ -2,7 +2,7 @@
#ifndef SIMPLE
#include "shaders/scene/material.glsl"
#include "shaders/scene/lightmodel.glsl"
#include "shaders/scene/lightmode.glsl"
#include "shaders/scene/light_shadow.glsl"
#include "shaders/scene/light_spot.glsl"

View file

@ -0,0 +1,142 @@
#include "shaders/scene/lightmode_default.glsl"
#include "shaders/scene/lightmode_software.glsl"
#include "shaders/scene/lightmode_vanilla.glsl"
#include "shaders/scene/lightmode_build.glsl"
#include "shaders/scene/material.glsl"
//===========================================================================
//
// Calculate light
//
// It is important to note that the light color is not desaturated
// due to ZDoom's implementation weirdness. Everything that's added
// on top of it, e.g. dynamic lights and glows are, though, because
// the objects emitting these lights are also.
//
// This is making this a bit more complicated than it needs to
// because we can't just desaturate the final fragment color.
//
//===========================================================================
vec4 getLightColor(Material material)
{
#if defined(LIGHTMODE_DEFAULT)
vec4 color = Lightmode_Default();
#elif defined(LIGHTMODE_SOFTWARE)
vec4 color = Lightmode_Software();
#elif defined(LIGHTMODE_VANILLA)
vec4 color = Lightmode_Vanilla();
#elif defined(LIGHTMODE_BUILD)
vec4 color = Lightmode_Build();
#endif
//
// handle glowing walls
//
if (uGlowTopColor.a > 0.0 && glowdist.x < uGlowTopColor.a)
{
color.rgb += desaturate(uGlowTopColor * (1.0 - glowdist.x / uGlowTopColor.a)).rgb;
}
if (uGlowBottomColor.a > 0.0 && glowdist.y < uGlowBottomColor.a)
{
color.rgb += desaturate(uGlowBottomColor * (1.0 - glowdist.y / uGlowBottomColor.a)).rgb;
}
color = min(color, 1.0);
// these cannot be safely applied by the legacy format where the implementation cannot guarantee that the values are set.
#if !defined LEGACY_USER_SHADER && !defined NO_LAYERS
//
// apply glow
//
color.rgb = mix(color.rgb, material.Glow.rgb, material.Glow.a);
//
// apply brightmaps
//
color.rgb = min(color.rgb + material.Bright.rgb, 1.0);
#endif
//
// apply lightmaps
//
if (vLightmap.z >= 0.0)
{
color.rgb += texture(LightMap, vLightmap).rgb;
}
//
// apply dynamic lights
//
vec4 frag = vec4(ProcessMaterialLight(material, color.rgb), material.Base.a * vColor.a);
//
// colored fog
//
#if defined(FOG_AFTER_LIGHTS)
// calculate fog factor
#if defined(FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#else
float fogdist = max(16.0, pixelpos.w);
#endif
float fogfactor = exp2 (uFogDensity * fogdist);
frag = vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
#endif
return frag;
}
// The color of the fragment if it is fully occluded by ambient lighting
vec3 AmbientOcclusionColor()
{
// calculate fog factor
#if defined(FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#else
float fogdist = max(16.0, pixelpos.w);
#endif
float fogfactor = exp2 (uFogDensity * fogdist);
return mix(uFogColor.rgb, vec3(0.0), fogfactor);
}
vec4 ProcessLightMode(Material material)
{
#ifdef SIMPLE2D // uses the fog color to add a color overlay
#ifdef TM_FOGLAYER
vec4 frag = material.Base;
float gray = grayscale(frag);
vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2;
frag = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a);
frag *= vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
return frag;
#else
vec4 frag = material.Base * vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
return frag;
#endif
#else
#ifdef TM_FOGLAYER
#if defined(FOG_BEFORE_LIGHTS) || defined(FOG_AFTER_LIGHTS)
#if defined(FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#else
float fogdist = max(16.0, pixelpos.w);
#endif
float fogfactor = exp2 (uFogDensity * fogdist);
return vec4(uFogColor.rgb, (1.0 - fogfactor) * material.Base.a * 0.75 * vColor.a);
#else
return vec4(uFogColor.rgb, material.Base.a * 0.75 * vColor.a);
#endif
#else
return getLightColor(material);
#endif
#endif
}

View file

@ -0,0 +1,21 @@
vec4 Lightmode_Build()
{
// z is the depth in view space, positive going into the screen
#if defined(SWLIGHT_RADIAL)
float z = distance(pixelpos.xyz, uCameraPos.xyz);
#else
float z = pixelpos.w;
#endif
// This is a lot more primitive than Doom's lighting...
float numShades = float(uPalLightLevels & 255);
float curshade = (1.0 - uLightLevel) * (numShades - 1.0);
float visibility = max(uGlobVis * uLightFactor * z, 0.0);
float shade = clamp((curshade + visibility), 0.0, numShades - 1.0);
float newlightlevel = 1.0 - clamp(shade * uLightDist, 0.0, 1.0);
vec4 color = vColor;
color.rgb *= newlightlevel;
return color;
}

View file

@ -0,0 +1,28 @@
vec4 Lightmode_Default()
{
vec4 color = vColor;
#if defined(FOG_BEFORE_LIGHTS)
// calculate fog factor
#if defined(FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#else
float fogdist = max(16.0, pixelpos.w);
#endif
float fogfactor = exp2 (uFogDensity * fogdist);
// brightening around the player for light mode 2
if (fogdist < uLightDist)
{
color.rgb *= uLightFactor - (fogdist / uLightDist) * (uLightFactor - 1.0);
}
// apply light diminishing through fog equation
color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor);
#endif
return color;
}

View file

@ -0,0 +1,32 @@
float SoftwareColormap(float light, float z)
{
float L = light * 255.0;
float vis = min(uGlobVis / z, 24.0 / 32.0);
float shade = 2.0 - (L + 12.0) / 128.0;
float lightscale = shade - vis;
return lightscale * 31.0;
}
vec4 Lightmode_Software()
{
// z is the depth in view space, positive going into the screen
#if defined(SWLIGHT_RADIAL)
float z = distance(pixelpos.xyz, uCameraPos.xyz);
#else
float z = pixelpos.w;
#endif
float colormap = SoftwareColormap(uLightLevel, z);
#if defined(SWLIGHT_BANDED)
colormap = floor(colormap) + 0.5;
#endif
// Result is the normalized colormap index (0 bright .. 1 dark)
float newlightlevel = 1.0 - clamp(colormap, 0.0, 31.0) / 32.0;
vec4 color = vColor;
color.rgb *= newlightlevel;
return color;
}

View file

@ -0,0 +1,63 @@
float VanillaWallColormap(float lightnum, float z, vec3 normal)
{
// R_ScaleFromGlobalAngle calculation
float projection = 160.0; // projection depends on SCREENBLOCKS!! 160 is the fullscreen value
vec2 line_v1 = pixelpos.xz; // in vanilla this is the first curline vertex
vec2 line_normal = normal.xz;
float texscale = projection * clamp(dot(normalize(uCameraPos.xz - line_v1), line_normal), 0.0, 1.0) / z;
float lightz = clamp(16.0 * texscale, 0.0, 47.0);
// scalelight[lightnum][lightz] lookup
float startmap = (15.0 - lightnum) * 4.0;
return startmap - lightz * 0.5;
}
float VanillaPlaneColormap(float lightnum, float z)
{
float lightz = clamp(z / 16.0f, 0.0, 127.0);
// zlight[lightnum][lightz] lookup
float startmap = (15.0 - lightnum) * 4.0;
float scale = 160.0 / (lightz + 1.0);
return startmap - scale * 0.5;
}
float VanillaColormap(float light, float z)
{
float lightnum = clamp(light * 15.0, 0.0, 15.0);
if (dot(vWorldNormal.xyz, vWorldNormal.xyz) > 0.5)
{
vec3 normal = normalize(vWorldNormal.xyz);
return mix(VanillaWallColormap(lightnum, z, normal), VanillaPlaneColormap(lightnum, z), abs(normal.y));
}
else // vWorldNormal is not set on sprites
{
return VanillaPlaneColormap(lightnum, z);
}
}
vec4 Lightmode_Vanilla()
{
// z is the depth in view space, positive going into the screen
#if defined(SWLIGHT_RADIAL)
float z = distance(pixelpos.xyz, uCameraPos.xyz);
#else
float z = pixelpos.w;
#endif
float colormap = VanillaColormap(uLightLevel, z);
#if defined(SWLIGHT_BANDED)
colormap = floor(colormap) + 0.5;
#endif
// Result is the normalized colormap index (0 bright .. 1 dark)
float newlightlevel = 1.0 - clamp(colormap, 0.0, 31.0) / 32.0;
vec4 color = vColor;
color.rgb *= newlightlevel;
return color;
}

View file

@ -1,129 +0,0 @@
#include "shaders/scene/lightmodel_software.glsl"
#include "shaders/scene/material.glsl"
//===========================================================================
//
// Calculate light
//
// It is important to note that the light color is not desaturated
// due to ZDoom's implementation weirdness. Everything that's added
// on top of it, e.g. dynamic lights and glows are, though, because
// the objects emitting these lights are also.
//
// This is making this a bit more complicated than it needs to
// because we can't just desaturate the final fragment color.
//
//===========================================================================
vec4 getLightColor(Material material)
{
// calculate fog factor
float fogdist = 0.0;
float fogfactor = 0.0;
if (uFogEnabled != 0)
{
if (uFogEnabled == 1 || uFogEnabled == -1)
{
fogdist = max(16.0, pixelpos.w);
}
else
{
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
}
fogfactor = exp2 (uFogDensity * fogdist);
}
vec4 color = vColor;
if (uLightLevel >= 0.0)
{
float newlightlevel = 1.0 - R_DoomLightingEquation(uLightLevel);
color.rgb *= newlightlevel;
}
else if (uFogEnabled > 0)
{
// brightening around the player for light mode 2
if (fogdist < uLightDist)
{
color.rgb *= uLightFactor - (fogdist / uLightDist) * (uLightFactor - 1.0);
}
//
// apply light diminishing through fog equation
//
color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor);
}
//
// handle glowing walls
//
if (uGlowTopColor.a > 0.0 && glowdist.x < uGlowTopColor.a)
{
color.rgb += desaturate(uGlowTopColor * (1.0 - glowdist.x / uGlowTopColor.a)).rgb;
}
if (uGlowBottomColor.a > 0.0 && glowdist.y < uGlowBottomColor.a)
{
color.rgb += desaturate(uGlowBottomColor * (1.0 - glowdist.y / uGlowBottomColor.a)).rgb;
}
color = min(color, 1.0);
// these cannot be safely applied by the legacy format where the implementation cannot guarantee that the values are set.
#if !defined LEGACY_USER_SHADER && !defined NO_LAYERS
//
// apply glow
//
color.rgb = mix(color.rgb, material.Glow.rgb, material.Glow.a);
//
// apply brightmaps
//
color.rgb = min(color.rgb + material.Bright.rgb, 1.0);
#endif
//
// apply lightmaps
//
if (vLightmap.z >= 0.0)
{
color.rgb += texture(LightMap, vLightmap).rgb;
}
//
// apply dynamic lights
//
vec4 frag = vec4(ProcessMaterialLight(material, color.rgb), material.Base.a * vColor.a);
//
// colored fog
//
if (uFogEnabled < 0)
{
frag = vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
}
return frag;
}
// The color of the fragment if it is fully occluded by ambient lighting
vec3 AmbientOcclusionColor()
{
float fogdist;
float fogfactor;
//
// calculate fog factor
//
if (uFogEnabled == -1)
{
fogdist = max(16.0, pixelpos.w);
}
else
{
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
}
fogfactor = exp2 (uFogDensity * fogdist);
return mix(uFogColor.rgb, vec3(0.0), fogfactor);
}

View file

@ -1,108 +0,0 @@
//===========================================================================
//
// Vanilla Doom wall colormap equation
//
//===========================================================================
float R_WallColormap(float lightnum, float z, vec3 normal)
{
// R_ScaleFromGlobalAngle calculation
float projection = 160.0; // projection depends on SCREENBLOCKS!! 160 is the fullscreen value
vec2 line_v1 = pixelpos.xz; // in vanilla this is the first curline vertex
vec2 line_normal = normal.xz;
float texscale = projection * clamp(dot(normalize(uCameraPos.xz - line_v1), line_normal), 0.0, 1.0) / z;
float lightz = clamp(16.0 * texscale, 0.0, 47.0);
// scalelight[lightnum][lightz] lookup
float startmap = (15.0 - lightnum) * 4.0;
return startmap - lightz * 0.5;
}
//===========================================================================
//
// Vanilla Doom plane colormap equation
//
//===========================================================================
float R_PlaneColormap(float lightnum, float z)
{
float lightz = clamp(z / 16.0f, 0.0, 127.0);
// zlight[lightnum][lightz] lookup
float startmap = (15.0 - lightnum) * 4.0;
float scale = 160.0 / (lightz + 1.0);
return startmap - scale * 0.5;
}
//===========================================================================
//
// zdoom colormap equation
//
//===========================================================================
float R_ZDoomColormap(float light, float z)
{
float L = light * 255.0;
float vis = min(uGlobVis / z, 24.0 / 32.0);
float shade = 2.0 - (L + 12.0) / 128.0;
float lightscale = shade - vis;
return lightscale * 31.0;
}
float R_DoomColormap(float light, float z)
{
if ((uPalLightLevels >> 16) == 16) // gl_lightmode 16
{
float lightnum = clamp(light * 15.0, 0.0, 15.0);
if (dot(vWorldNormal.xyz, vWorldNormal.xyz) > 0.5)
{
vec3 normal = normalize(vWorldNormal.xyz);
return mix(R_WallColormap(lightnum, z, normal), R_PlaneColormap(lightnum, z), abs(normal.y));
}
else // vWorldNormal is not set on sprites
{
return R_PlaneColormap(lightnum, z);
}
}
else
{
return R_ZDoomColormap(light, z);
}
}
//===========================================================================
//
// Doom software lighting equation
//
//===========================================================================
float R_DoomLightingEquation(float light)
{
// z is the depth in view space, positive going into the screen
float z;
if (((uPalLightLevels >> 8) & 0xff) == 2)
{
z = distance(pixelpos.xyz, uCameraPos.xyz);
}
else
{
z = pixelpos.w;
}
if ((uPalLightLevels >> 16) == 5) // gl_lightmode 5: Build software lighting emulation.
{
// This is a lot more primitive than Doom's lighting...
float numShades = float(uPalLightLevels & 255);
float curshade = (1.0 - light) * (numShades - 1.0);
float visibility = max(uGlobVis * uLightFactor * z, 0.0);
float shade = clamp((curshade + visibility), 0.0, numShades - 1.0);
return clamp(shade * uLightDist, 0.0, 1.0);
}
float colormap = R_DoomColormap(light, z);
if ((uPalLightLevels & 0xff) != 0)
colormap = floor(colormap) + 0.5;
// Result is the normalized colormap index (0 bright .. 1 dark)
return clamp(colormap, 0.0, 31.0) / 32.0;
}