Skip to content

Commit 35b757b

Browse files
committed
try to limit lighting change based on normal change
1 parent c95cc61 commit 35b757b

2 files changed

Lines changed: 37 additions & 9 deletions

File tree

src/engine/renderer/glsl_source/computeLight_fp.glsl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ vec4 EnvironmentalSpecularFactor( vec3 viewDir, vec3 normal )
7272

7373
#if defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) || defined(r_realtimeLighting)
7474
void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor,
75-
vec4 diffuseColor, vec4 materialColor,
75+
vec3 lambertTerm, vec4 diffuseColor, vec4 materialColor,
7676
inout vec4 color )
7777
{
7878
vec3 H = normalize( lightDir + viewDir );
@@ -92,6 +92,10 @@ void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightCol
9292

9393
NdotL = clamp( NdotL, 0.0, 1.0 );
9494

95+
#if !defined(USE_LIGHT_MAPPING)
96+
lambertTerm = NdotL * lightColor;
97+
#endif
98+
9599
#if defined(USE_PHYSICAL_MAPPING)
96100
// Daemon PBR packing defaults to ORM like glTF 2.0 defines
97101
// https://www.khronos.org/blog/art-pipeline-for-gltf
@@ -124,11 +128,11 @@ void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightCol
124128

125129
vec3 diffuseBRDF = NdotL * diffuseColor.rgb * ( 1.0 - metalness );
126130
vec3 specularBRDF = vec3( ( D * F * G ) / max( 4.0 * NdotL * NdotV, 0.0001f ) );
127-
color.rgb += ( diffuseBRDF + specularBRDF ) * lightColor.rgb * NdotL;
131+
color.rgb += ( diffuseBRDF + specularBRDF ) * lambertTerm;
128132
color.a = mix( diffuseColor.a, 1.0, FexpNV );
129133

130134
#else // !USE_PHYSICAL_MAPPING
131-
color.rgb += lightColor.rgb * NdotL * diffuseColor.rgb;
135+
color.rgb += lambertTerm * diffuseColor.rgb;
132136
#if defined(r_specularMapping)
133137
color.rgb += computeSpecularity(lightColor.rgb, materialColor, NdotH);
134138
#endif // r_specularMapping
@@ -198,8 +202,9 @@ void computeDynamicLight( uint idx, vec3 P, vec3 normal, vec3 viewDir, vec4 diff
198202
attenuation = 1.0;
199203
}
200204

205+
vec3 attenuatedColor = attenuation * attenuation * light.color;
201206
computeDeluxeLight(
202-
L, normal, viewDir, attenuation * attenuation * light.color,
207+
L, normal, viewDir, attenuatedColor, dot(L, normal) * attenuatedColor,
203208
diffuse, material, color );
204209
}
205210

src/engine/renderer/glsl_source/lightMapping_fp.glsl

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ void main()
163163
#endif
164164

165165
#if defined(USE_LIGHT_MAPPING) && defined(USE_DELUXE_MAPPING)
166+
vec3 lightmapValue = lightColor;
167+
166168
/* Lightmaps generated by q3map2 don't store the raw light value, but
167169
they store light premultiplied with the dot product of the light
168170
direction and surface normal. The line is just an attempt to reverse
@@ -183,18 +185,39 @@ void main()
183185
Increasing the value should reduce these artifacts. -- gimhael
184186
https://github.com/DaemonEngine/Daemon/issues/299#issuecomment-606186347
185187
*/
186-
187-
// Divide by cosine term to restore original light color.
188-
lightColor /= clamp(dot(normalize(var_Normal), lightDir), 0.3, 1.0);
188+
vec3 flatNormal = normalize(var_Normal);
189+
float flatNdotL = clamp(dot(flatNormal, lightDir), 0.3, 1.0);
190+
lightColor /= flatNdotL;
191+
192+
// The light direction from the deluxe map may be nonsense, be it because q3map2
193+
// goofed, or because the light actually comes from more than one direction(!!!!). The total, summed
194+
// over light sources, of (light color) * dot(flat triangle's normal, light direction), as given by the lightmap, is more
195+
// trustworthy. If the normalmapped normal is almost the same as the the original flat geometry's normal,
196+
// we can bound how much the above sum can change, thus preventing the bogus light direction from
197+
// wrecking the Lambert's law term of our lighting equation.
198+
// So we want to compute the maximum of
199+
// abs(dot(var_Normal, L) - dot(normal, L))
200+
// = abs(dot(normal - var_Normal, L))
201+
// over all possible L. This maximum occurs when L is parallel to normal - var_Normal.
202+
float dotDelta = length(normal - flatNormal);
203+
// So each dot product term can only increase or decrease by dotDelta. But we don't know
204+
// what the original dot products were. We'll have to assume a maximum angle to be able to
205+
// bound the percent change of the total.
206+
float minimumAverageCosine = 0.1; // 84.3 degrees
207+
float cosinesRatio = dot(normal, lightDir) / flatNdotL;
208+
cosinesRatio = clamp( cosinesRatio, 1.0 - dotDelta / minimumAverageCosine, 1.0 + dotDelta / minimumAverageCosine );
209+
vec3 lambertTerm = lightmapValue * cosinesRatio;
210+
#else
211+
vec3 lambertTerm; // not used
189212
#endif
190213

191214
// Blend static light.
192215
#if defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING)
193216
#if defined(USE_REFLECTIVE_SPECULAR)
194217
vec4 modifiedSpecular = material * EnvironmentalSpecularFactor(viewDir, normal);
195-
computeDeluxeLight(lightDir, normal, viewDir, lightColor, diffuse, modifiedSpecular, color);
218+
computeDeluxeLight(lightDir, normal, viewDir, lightColor, lambertTerm, diffuse, modifiedSpecular, color);
196219
#else // !USE_REFLECTIVE_SPECULAR
197-
computeDeluxeLight(lightDir, normal, viewDir, lightColor, diffuse, material, color);
220+
computeDeluxeLight(lightDir, normal, viewDir, lightColor, lambertTerm, diffuse, material, color);
198221
#endif // !USE_REFLECTIVE_SPECULAR
199222
#else
200223
computeLight(lightColor, diffuse, color);

0 commit comments

Comments
 (0)