From 38fdddf4aa49fdaa7db53d537aa3c09d0a4b37fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Wed, 21 May 2025 08:44:45 +0200 Subject: [PATCH] area light improvements --- WickedEngine/shaders/lightCullingCS.hlsl | 2 +- WickedEngine/shaders/lightingHF.hlsli | 15 ++++++++++++--- WickedEngine/shaders/objectHF.hlsli | 1 + WickedEngine/shaders/vRectLightPS.hlsl | 2 +- WickedEngine/wiVersion.cpp | 2 +- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/WickedEngine/shaders/lightCullingCS.hlsl b/WickedEngine/shaders/lightCullingCS.hlsl index cc14be7a4..e6c0b5716 100644 --- a/WickedEngine/shaders/lightCullingCS.hlsl +++ b/WickedEngine/shaders/lightCullingCS.hlsl @@ -272,7 +272,7 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : if (entity.IsStaticLight()) continue; // static lights will be skipped here (they are used at lightmap baking) float3 positionVS = mul(GetCamera().view, float4(entity.position, 1)).xyz; - Sphere sphere = { positionVS.xyz, entity.GetRange() }; + Sphere sphere = { positionVS.xyz, max(entity.GetLength(), entity.GetHeight()) + entity.GetRange() }; if (SphereInsideFrustum(sphere, GroupFrustum, nearClipVS, maxDepthVS)) { AppendEntity_Transparent(i); diff --git a/WickedEngine/shaders/lightingHF.hlsli b/WickedEngine/shaders/lightingHF.hlsli index 5942540ad..373960598 100644 --- a/WickedEngine/shaders/lightingHF.hlsli +++ b/WickedEngine/shaders/lightingHF.hlsli @@ -425,6 +425,7 @@ inline void light_rect(in ShaderEntity light, in Surface surface, inout Lighting const half3 forward = cross(up, right); const half light_length = max(0.01, light.GetLength()); const half light_height = max(0.01, light.GetHeight()); + const half light_area = light_length * light_height; const float3 p0 = light.position - right * light_length * 0.5 + up * light_height * 0.5; const float3 p1 = light.position + right * light_length * 0.5 + up * light_height * 0.5; const float3 p2 = light.position + right * light_length * 0.5 - up * light_height * 0.5; @@ -432,8 +433,15 @@ inline void light_rect(in ShaderEntity light, in Surface surface, inout Lighting if (dot(surface.P - light.position, forward) <= 0) return; // behind light + + // Determine closest point on rectangle to surface position: + float3 closest_point_on_plane_to_surface = point_on_plane(surface.P, light.position, forward); + float3 closest_vector_on_plane = closest_point_on_plane_to_surface - light.position; + float2 plane_point = float2(dot(closest_vector_on_plane, right), dot(closest_vector_on_plane, up)); + float2 nearest_point = float2(clamp(plane_point.x, -light_length * 0.5, light_length * 0.5), clamp(plane_point.y, -light_height * 0.5, light_height * 0.5)); + float3 rectangle_point = light.position + nearest_point.x * right + nearest_point.y * up; - float3 Lunnormalized = light.position - surface.P; + float3 Lunnormalized = rectangle_point - surface.P; const half dist2 = dot(Lunnormalized, Lunnormalized); const half range = light.GetRange(); @@ -449,6 +457,7 @@ inline void light_rect(in ShaderEntity light, in Surface surface, inout Lighting surface_to_light.create(surface, L); // Solid angle based on the Frostbite presentation: Moving Frostbite to Physically Based Rendering by Sebastien Lagarde, Charles de Rousiers, Siggraph 2014 + // https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/course-notes-moving-frostbite-to-pbr-v2.pdf float3 v0 = normalize(p0 - surface.P); float3 v1 = normalize(p1 - surface.P); float3 v2 = normalize(p2 - surface.P); @@ -501,9 +510,9 @@ inline void light_rect(in ShaderEntity light, in Surface surface, inout Lighting return; // light color lost after shadow } - light_color *= attenuation_pointlight(dist2, range, range2); + light_color *= attenuation_pointlight(dist2, range, range2); // dist2 is the closest point on rectangle, so it will not be a falloff from light center, but as if a point light is placed on the closest rectangle point - half3 light_color_diffuse = light_color; + half3 light_color_diffuse = light_color * light_area * PI; // I increase the light color by the surface area, because I want larger lights to illuminate more. half3 light_color_specular = light_color; diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli index 731c92e12..c2ef8cc87 100644 --- a/WickedEngine/shaders/objectHF.hlsli +++ b/WickedEngine/shaders/objectHF.hlsli @@ -545,6 +545,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace APPEND_COVER input.nor = -input.nor; } surface.N = normalize(input.nor); + surface.facenormal = surface.N; #endif // OBJECTSHADER_USE_NORMAL #ifdef OBJECTSHADER_USE_COMMON diff --git a/WickedEngine/shaders/vRectLightPS.hlsl b/WickedEngine/shaders/vRectLightPS.hlsl index d1349643d..a94e84505 100644 --- a/WickedEngine/shaders/vRectLightPS.hlsl +++ b/WickedEngine/shaders/vRectLightPS.hlsl @@ -2,7 +2,7 @@ float4 main(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_TARGET { - float4 color = float4(xLightColor.rgb * xLightEnerdis.x / (2 * PI), 1); // 2*PI: balance the displaying of light visualizer with the diffuse strength of lighting. + float4 color = float4(xLightColor.rgb * xLightEnerdis.x, 1); int maskTexDescriptor = (int)xLightEnerdis.y; if (maskTexDescriptor >= 0) diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 392fdd0cb..1ec00bec5 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 772; + const int revision = 773; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);