diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index 12c4bc6ba..0547e62e8 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -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; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 88ec82f2f..15dad9ac7 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -181,8 +181,8 @@ std::unique_ptr 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) { @@ -195,6 +195,20 @@ std::unique_ptr 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"; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index ceaec62ab..5f3b9ddf1 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -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; }; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 73d047337..c67bebc62 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -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; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index a4133aa3b..c2dcdb854 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -481,6 +481,8 @@ void HWDrawInfo::RenderScene(FRenderState &state) const auto &vp = Viewpoint; RenderAll.Clock(); + state.SetLightMode((int)lightmode); + state.SetDepthMask(true); state.EnableFog(true); diff --git a/wadsrc/static/shaders/scene/frag_main.glsl b/wadsrc/static/shaders/scene/frag_main.glsl index edaef7a9f..ba3987517 100644 --- a/wadsrc/static/shaders/scene/frag_main.glsl +++ b/wadsrc/static/shaders/scene/frag_main.glsl @@ -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); diff --git a/wadsrc/static/shaders/scene/includes.glsl b/wadsrc/static/shaders/scene/includes.glsl index e527b0aed..83ac427b3 100644 --- a/wadsrc/static/shaders/scene/includes.glsl +++ b/wadsrc/static/shaders/scene/includes.glsl @@ -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" diff --git a/wadsrc/static/shaders/scene/lightmode.glsl b/wadsrc/static/shaders/scene/lightmode.glsl new file mode 100644 index 000000000..0f138c55f --- /dev/null +++ b/wadsrc/static/shaders/scene/lightmode.glsl @@ -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 +} diff --git a/wadsrc/static/shaders/scene/lightmode_build.glsl b/wadsrc/static/shaders/scene/lightmode_build.glsl new file mode 100644 index 000000000..9298a36ff --- /dev/null +++ b/wadsrc/static/shaders/scene/lightmode_build.glsl @@ -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; +} diff --git a/wadsrc/static/shaders/scene/lightmode_default.glsl b/wadsrc/static/shaders/scene/lightmode_default.glsl new file mode 100644 index 000000000..e26826510 --- /dev/null +++ b/wadsrc/static/shaders/scene/lightmode_default.glsl @@ -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; +} diff --git a/wadsrc/static/shaders/scene/lightmode_software.glsl b/wadsrc/static/shaders/scene/lightmode_software.glsl new file mode 100644 index 000000000..2b1048e82 --- /dev/null +++ b/wadsrc/static/shaders/scene/lightmode_software.glsl @@ -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; +} diff --git a/wadsrc/static/shaders/scene/lightmode_vanilla.glsl b/wadsrc/static/shaders/scene/lightmode_vanilla.glsl new file mode 100644 index 000000000..a47c09567 --- /dev/null +++ b/wadsrc/static/shaders/scene/lightmode_vanilla.glsl @@ -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; +} diff --git a/wadsrc/static/shaders/scene/lightmodel.glsl b/wadsrc/static/shaders/scene/lightmodel.glsl deleted file mode 100644 index c6fc3c7dc..000000000 --- a/wadsrc/static/shaders/scene/lightmodel.glsl +++ /dev/null @@ -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); -} diff --git a/wadsrc/static/shaders/scene/lightmodel_software.glsl b/wadsrc/static/shaders/scene/lightmodel_software.glsl deleted file mode 100644 index 84fc7dec4..000000000 --- a/wadsrc/static/shaders/scene/lightmodel_software.glsl +++ /dev/null @@ -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; -}