summaryrefslogtreecommitdiff
path: root/src/rend2/glsl
diff options
context:
space:
mode:
authorJames Canete <use.less01@gmail.com>2012-12-10 22:35:57 +0000
committerTim Angus <tim@ngus.net>2013-01-12 21:24:55 +0000
commit055c011034b61634c467017530e924dd109cc716 (patch)
treea4a6e04d8c05bc8dff66e226decd44627e11c578 /src/rend2/glsl
parentd5e6aff20dbc6b1f2bad90260de70eae6c2ea75b (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.glsl44
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;