diff options
author | James Canete <use.less01@gmail.com> | 2012-12-10 22:35:57 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-12 21:24:55 +0000 |
commit | 055c011034b61634c467017530e924dd109cc716 (patch) | |
tree | a4a6e04d8c05bc8dff66e226decd44627e11c578 /src/rend2/glsl | |
parent | d5e6aff20dbc6b1f2bad90260de70eae6c2ea75b (diff) |
Split light sample into direct and ambient parts when using deluxemaps or per-vertex light vectors. Fixes #5813.
Diffstat (limited to 'src/rend2/glsl')
-rw-r--r-- | src/rend2/glsl/lightall_fp.glsl | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/src/rend2/glsl/lightall_fp.glsl b/src/rend2/glsl/lightall_fp.glsl index f7e091ac..186ea4b0 100644 --- a/src/rend2/glsl/lightall_fp.glsl +++ b/src/rend2/glsl/lightall_fp.glsl @@ -300,28 +300,54 @@ void main() #elif defined(USE_LIGHT) worldLight = normalize(worldLight); + float surfNL = clamp(dot(surfNormal, worldLight), 0.0, 1.0); + #if defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX) - #if defined(r_normalAmbient) - vec3 ambientLight = directedLight * r_normalAmbient; - directedLight -= ambientLight; - #else + #if defined(USE_STANDARD_DELUXEMAP) + // Standard deluxe mapping treats the light sample as fully directed + // and doesn't compensate for light angle attenuation. vec3 ambientLight = vec3(0.0); + #else + // Separate the light sample into directed and ambient parts. + // + // ambientMax - if the cosine of the angle between the surface + // normal and the light is below this value, the light + // is fully ambient. + // directedMax - if the cosine of the angle between the surface + // normal and the light is above this value, the light + // is fully directed. + const float ambientMax = 0.25; + const float directedMax = 0.5; + + float directedScale = clamp((surfNL - ambientMax) / (directedMax - ambientMax), 0.0, 1.0); + + // Scale the directed portion to compensate for the baked-in + // light angle attenuation. + directedScale /= max(surfNL, ambientMax); + + #if defined(r_normalAmbient) + directedScale *= 1.0 - r_normalAmbient; + #endif + + // Recover any unused light as ambient + vec3 ambientLight = directedLight; + directedLight *= directedScale; + ambientLight -= directedLight * surfNL; #endif - directedLight /= max(dot(surfNormal, worldLight), 0.004); #endif - + float NL = clamp(dot(worldNormal, worldLight), 0.0, 1.0); - float surfNL = clamp(dot(surfNormal, worldLight), 0.0, 1.0); - NL = min(NL, surfNL * 2.0); float NE = clamp(dot(worldNormal, SampleToView), 0.0, 1.0); - + float fzero = u_MaterialInfo.x; float shininess = u_MaterialInfo.y; + #if defined(USE_SPECULARMAP) vec4 specular = texture2D(u_SpecularMap, tex); //specular.rgb = clamp(specular.rgb - diffuse.rgb, 0.0, 1.0); shininess *= specular.a; #endif + float directedDiff = NL * CalcDiffuse(worldNormal, worldLight, SampleToView, NE, NL, fzero, shininess); diffuse.rgb *= directedLight * directedDiff + ambientDiff * ambientLight; |