diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp index 26f42d7a2..5e06456cb 100644 --- a/src/gl/dynlights/gl_dynlight1.cpp +++ b/src/gl/dynlights/gl_dynlight1.cpp @@ -109,8 +109,9 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD i = 1; } - float shadowIndex = (float)GLRenderer->mShadowMap.ShadowMapIndex(light); - if (!!(light->flags4 & MF4_ATTENUATE)) // Store attenuate flag in the sign bit of the float + // Store attenuate flag in the sign bit of the float. + float shadowIndex = GLRenderer->mShadowMap.ShadowMapIndex(light) + 1.0f; + if (!!(light->flags4 & MF4_ATTENUATE)) shadowIndex = -shadowIndex; float *data = &ldata.arrays[i][ldata.arrays[i].Reserve(8)]; diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index b6bb0d9b0..9a682f386 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -141,10 +141,9 @@ float R_DoomLightingEquation(float light) #ifdef SUPPORTS_SHADOWMAPS -float sampleShadowmap(vec2 lightpos, vec2 testpos, float v) +float sampleShadowmap(vec2 dir, float v) { float u; - vec2 dir = (testpos - lightpos); if (abs(dir.x) > abs(dir.y)) { if (dir.x >= 0.0) @@ -159,7 +158,6 @@ float sampleShadowmap(vec2 lightpos, vec2 testpos, float v) else u = dir.x / dir.y * 0.125 + (0.50 + 0.125); } - dir -= sign(dir) * 2.0; // margin, to remove wall acne float dist2 = dot(dir, dir); return texture(ShadowMap, vec2(u, v)).x > dist2 ? 1.0 : 0.0; } @@ -175,16 +173,28 @@ float sampleShadowmap(vec2 lightpos, vec2 testpos, float v) float shadowmapAttenuation(vec4 lightpos, float shadowIndex) { - if (shadowIndex <= -1024.0 || shadowIndex >= 1024.0) + if (shadowIndex >= 1024.0) return 1.0; // No shadowmap available for this light - float v = (abs(shadowIndex) + 0.5) / 1024.0; - vec2 dir = (pixelpos.xz - lightpos.xz); - vec2 normal = normalize(vec2(-dir.y, dir.x)); + float v = (shadowIndex + 0.5) / 1024.0; + + vec2 ray = pixelpos.xz - lightpos.xz; + float length = length(ray); + if (length < 3.0) + return 1.0; + + vec2 dir = ray / length; + + ray -= dir * 2.0; // margin + dir = dir * min(length / 50.0, 1.0); // avoid sampling behind light + + vec2 normal = vec2(-dir.y, dir.x); + vec2 bias = dir * 10.0; + float sum = 0.0; for (float x = -PCF_FILTER_STEP_COUNT; x <= PCF_FILTER_STEP_COUNT; x++) { - sum += sampleShadowmap(lightpos.xz, pixelpos.xz + normal * x, v); + sum += sampleShadowmap(ray + normal * x - bias * abs(x), v); } return sum / PCF_COUNT; } @@ -210,13 +220,14 @@ float diffuseContribution(vec3 lightDirection, vec3 normal) // //=========================================================================== -float pointLightAttenuation(vec4 lightpos, float shadowIndex) +float pointLightAttenuation(vec4 lightpos, float lightcolorA) { float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w; #ifdef SUPPORTS_SHADOWMAPS + float shadowIndex = abs(lightcolorA) - 1.0; attenuation *= shadowmapAttenuation(lightpos, shadowIndex); #endif - if (shadowIndex >= 0.0) // Sign bit is the attenuated light flag + if (lightcolorA >= 0.0) // Sign bit is the attenuated light flag { return attenuation; }