@@ -23,7 +23,7 @@ struct VSOutput {
2323
2424// Light data structure for storage buffer
2525struct LightData {
26- float4 position; // Light position (w component unused )
26+ float4 position; // Light position (w component 1 for directional )
2727 float4 color; // Light color and intensity
2828 float4x4 lightSpaceMatrix; // Light space matrix for shadow mapping
2929 int lightType; // 0=Point, 1=Directional, 2=Spot, 3=Emissive
@@ -217,40 +217,64 @@ float4 PSMain(VSOutput input) : SV_TARGET
217217 // Calculate lighting for each light (dynamic count - no limit)
218218 for (int i = 0 ; i < ubo .lightCount ; i++ ) {
219219 LightData light = lightBuffer [i];
220- float3 lightPos = light .position .xyz ;
220+ float3 lightPos = mul(light .lightSpaceMatrix , float4(input .WorldPos , 1 . 0 )).xyz ;
221+ float3 lightVec = light .position .xyz ;
221222 float3 lightColor = light .color .rgb ;
222223
223224 // Handle emissive lights differently
224225 if (light .lightType == 3 ) { // Emissive light
225- // For emissive lights, treat them as area lights with enhanced contribution
226- // Calculate light direction and distance
226+ // Treat emissive like a positional contributor from its stored position
227227 float3 L = normalize(lightPos - input .WorldPos );
228228 float distance = length(lightPos - input .WorldPos );
229+ float attenuation = 1 . 0 / (distance * distance);
230+ float3 radiance = lightColor * attenuation;
231+
232+ float3 H = normalize(V + L);
233+
234+ float NdotL = max(dot(N, L), 0 . 0 );
235+ float NdotV = max(dot(N, V), 0 . 0 );
236+ float NdotH = max(dot(N, H), 0 . 0 );
237+ float HdotV = max(dot(H, V), 0 . 0 );
238+
239+ float shadow = 0 . 0 ;
240+ if (i < ubo .shadowMapCount ) {
241+ float4 fragPosLightSpace = mul(light .lightSpaceMatrix , float4(input .WorldPos , 1 . 0 ));
242+ shadow = calculateShadow(fragPosLightSpace, i, N, L);
243+ }
229244
230- // Enhanced attenuation for emissive lights to make them more effective
231- float attenuation = 1 . 0 / (1 . 0 + 0 . 1 * distance + 0 . 01 * distance * distance);
245+ float D = DistributionGGX(NdotH, roughness);
246+ float G = GeometrySmith(NdotV, NdotL, roughness);
247+ float3 F = FresnelSchlick(HdotV, F0);
248+
249+ float3 numerator = D * G * F;
250+ float denominator = 4 . 0 * NdotV * NdotL + 0 . 0001 ;
251+ float3 specular = numerator / denominator;
252+
253+ float3 kS = F;
254+ float3 kD = float3(1 . 0 , 1 . 0 , 1 . 0 ) - kS;
255+ kD *= 1 . 0 - metallic;
256+
257+ float shadowFactor = 1 . 0 - shadow;
258+ Lo += (kD * baseColor .rgb / PI + specular) * radiance * NdotL * shadowFactor;
232259
233- // Boost emissive light intensity to make them more visible
234- float3 radiance = lightColor * attenuation * 2 . 0 ; // 2x multiplier for emissive lights
260+ } else if (light .lightType == 1 ) { // Directional light
261+ // For directional lights, position field stores direction; use no distance attenuation
262+ float3 L = normalize(- lightVec); // light direction towards the surface
263+ float3 radiance = lightColor; // No attenuation with distance
235264
236- // Calculate half vector
237265 float3 H = normalize(V + L);
238266
239- // Calculate BRDF terms
240267 float NdotL = max(dot(N, L), 0 . 0 );
241268 float NdotV = max(dot(N, V), 0 . 0 );
242269 float NdotH = max(dot(N, H), 0 . 0 );
243270 float HdotV = max(dot(H, V), 0 . 0 );
244271
245- // Calculate shadow factor for emissive lights
246272 float shadow = 0 . 0 ;
247273 if (i < ubo .shadowMapCount ) {
248- // Transform fragment position to light space
249274 float4 fragPosLightSpace = mul(light .lightSpaceMatrix , float4(input .WorldPos , 1 . 0 ));
250275 shadow = calculateShadow(fragPosLightSpace, i, N, L);
251276 }
252277
253- // Specular BRDF
254278 float D = DistributionGGX(NdotH, roughness);
255279 float G = GeometrySmith(NdotV, NdotL, roughness);
256280 float3 F = FresnelSchlick(HdotV, F0);
@@ -259,40 +283,32 @@ float4 PSMain(VSOutput input) : SV_TARGET
259283 float denominator = 4 . 0 * NdotV * NdotL + 0 . 0001 ;
260284 float3 specular = numerator / denominator;
261285
262- // Energy conservation
263286 float3 kS = F;
264287 float3 kD = float3(1 . 0 , 1 . 0 , 1 . 0 ) - kS;
265288 kD *= 1 . 0 - metallic;
266289
267- // Apply shadow factor to lighting
268290 float shadowFactor = 1 . 0 - shadow;
269291 Lo += (kD * baseColor .rgb / PI + specular) * radiance * NdotL * shadowFactor;
270292
271- } else { // Regular lights (Point, Directional, Spot)
272- // Calculate light direction and distance
293+ } else { // Point/Spot lights
273294 float3 L = normalize(lightPos - input .WorldPos );
274295 float distance = length(lightPos - input .WorldPos );
275296 float attenuation = 1 . 0 / (distance * distance);
276297 float3 radiance = lightColor * attenuation;
277298
278- // Calculate half vector
279299 float3 H = normalize(V + L);
280300
281- // Calculate BRDF terms
282301 float NdotL = max(dot(N, L), 0 . 0 );
283302 float NdotV = max(dot(N, V), 0 . 0 );
284303 float NdotH = max(dot(N, H), 0 . 0 );
285304 float HdotV = max(dot(H, V), 0 . 0 );
286305
287- // Calculate shadow factor
288306 float shadow = 0 . 0 ;
289307 if (i < ubo .shadowMapCount ) {
290- // Transform fragment position to light space
291308 float4 fragPosLightSpace = mul(light .lightSpaceMatrix , float4(input .WorldPos , 1 . 0 ));
292309 shadow = calculateShadow(fragPosLightSpace, i, N, L);
293310 }
294311
295- // Specular BRDF
296312 float D = DistributionGGX(NdotH, roughness);
297313 float G = GeometrySmith(NdotV, NdotL, roughness);
298314 float3 F = FresnelSchlick(HdotV, F0);
@@ -301,12 +317,10 @@ float4 PSMain(VSOutput input) : SV_TARGET
301317 float denominator = 4 . 0 * NdotV * NdotL + 0 . 0001 ;
302318 float3 specular = numerator / denominator;
303319
304- // Energy conservation
305320 float3 kS = F;
306321 float3 kD = float3(1 . 0 , 1 . 0 , 1 . 0 ) - kS;
307322 kD *= 1 . 0 - metallic;
308323
309- // Apply shadow factor to lighting (1.0 - shadow means 0 shadow = full light, 1 shadow = no light)
310324 float shadowFactor = 1 . 0 - shadow;
311325 Lo += (kD * baseColor .rgb / PI + specular) * radiance * NdotL * shadowFactor;
312326 }
0 commit comments