diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index aca76d2..4bece97 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -801,10 +801,6 @@ void CNew3D::RenderViewport(UINT32 addr) vp->spotRange[0] = 1.0f / (*(float *)&vpnode[0x21]); // spotlight start vp->spotRange[1] = *(float *)&vpnode[0x1F]; // spotlight extent - // Star Wars Trilogy needs this - vp->spotRange[0] = std::min(vp->spotRange[0], std::numeric_limits::max()); - vp->spotRange[0] = std::max(vp->spotRange[0], std::numeric_limits::lowest()); - vp->spotColor[0] = color[spotColorIdx][0]; // spotlight color vp->spotColor[1] = color[spotColorIdx][1]; vp->spotColor[2] = color[spotColorIdx][2]; diff --git a/Src/Graphics/New3D/R3DShader.cpp b/Src/Graphics/New3D/R3DShader.cpp index 63c217f..e472e8d 100644 --- a/Src/Graphics/New3D/R3DShader.cpp +++ b/Src/Graphics/New3D/R3DShader.cpp @@ -164,12 +164,40 @@ void main() float ellipse; ellipse = length((gl_FragCoord.xy - spotEllipse.xy) / spotEllipse.zw); ellipse = pow(ellipse, 2.0); // decay rate = square of distance from center - ellipse = 1.0 - ellipse; // invert - ellipse = max(0.0, ellipse); // clamp - - if (lightEnabled) { - vec3 lightIntensity; - vec3 sunVector; // sun lighting vector (as reflecting away from vertex) + ellipse = 1.0 - ellipse; // invert + ellipse = max(0.0, ellipse); // clamp + + // Compute spotlight and apply lighting + float enable, absExtent, d, inv_r, range; + + // start of spotlight + enable = step(spotRange.x, -fsViewVertex.z); + + if (spotRange.y == 0.0) { + range = 0.0; + } + else { + absExtent = abs(spotRange.y); + + d = spotRange.x + absExtent + fsViewVertex.z; + d = min(d, 0.0); + + // slope of decay function + inv_r = 1.0 / (1.0 + absExtent); + + // inverse-linear falloff + // Reference: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/ + // y = 1 / (d/r + 1)^2 + range = 1.0 / pow(d * inv_r - 1.0, 2.0); + range *= enable; + } + + float lobeEffect = range * ellipse; + float lobeFogEffect = enable * ellipse; + + if (lightEnabled) { + vec3 lightIntensity; + vec3 sunVector; // sun lighting vector (as reflecting away from vertex) float sunFactor; // sun light projection along vertex normal (0.0 to 1.0) // Sun angle @@ -196,28 +224,12 @@ void main() // Upper clamp is optional, step 1.5+ games will drive brightness beyond 100% if(intensityClamp) { - lightIntensity = min(lightIntensity,1.0); - } - - // Compute spotlight and apply lighting - float enable, range, d; - float inv_r = 1.0 / spotEllipse.z; // slope of decay function - - d = spotRange.x + spotRange.y + fsViewVertex.z; - enable = step(spotRange.x + min(spotRange.y, 0.0), -fsViewVertex.z); - - // inverse-linear falloff - // Reference: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/ - // y = 1 / (d/r + 1)^2 - range = 1.0 / pow(min(0.0, d * inv_r) - 1.0, 2.0); - range = clamp(range, 0.0, 1.0); - range *= enable; - - float lobeEffect = range * ellipse; - - lightIntensity.rgb += spotColor*lobeEffect; - - finalData.rgb *= lightIntensity; + lightIntensity = min(lightIntensity,1.0); + } + + lightIntensity.rgb += spotColor*lobeEffect; + + finalData.rgb *= lightIntensity; // for now assume fixed shading doesn't work with specular if (specularEnabled && !fixedShading) { @@ -250,16 +262,16 @@ void main() } // Final clamp: we need it for proper shading in dimmed light and dark ambients - finalData.rgb = min(finalData.rgb, vec3(1.0)); - - // Spotlight on fog - vec3 lSpotFogColor = spotFogColor * ellipse * fogColour.rgb; - - // Fog & spotlight applied - finalData.rgb = mix(finalData.rgb, lSpotFogColor * fogAttenuation + fogData.rgb, fogData.a); - - gl_FragColor = finalData; -} + finalData.rgb = min(finalData.rgb, vec3(1.0)); + + // Spotlight on fog + vec3 lSpotFogColor = spotFogColor * fogAttenuation * fogColour.rgb * lobeFogEffect; + + // Fog & spotlight applied + finalData.rgb = mix(finalData.rgb, fogData.rgb + lSpotFogColor, fogData.a); + + gl_FragColor = finalData; +} )glsl"; R3DShader::R3DShader(const Util::Config::Node &config)