From cd49d5b869d59d9764cc9c5361012a91782a454a Mon Sep 17 00:00:00 2001 From: Anish Bhobe Date: Wed, 24 Jul 2024 19:59:55 +0200 Subject: [PATCH] Directional Light PBR. --- samples/03_model_render/model_render.cpp | 2 +- .../shader/bindless_structs.hlsli | 2 +- samples/03_model_render/shader/model.ps.hlsl | 91 ++++++++++++++----- 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/samples/03_model_render/model_render.cpp b/samples/03_model_render/model_render.cpp index 83a94e8..11b9ea4 100644 --- a/samples/03_model_render/model_render.cpp +++ b/samples/03_model_render/model_render.cpp @@ -90,7 +90,7 @@ main(int, char **) .m_Position = vec4{0.0f, 2.0f, 2.0f, 1.0f}, }; - //lightManager.AddDirectional(vec3(0.0f, -1.0f, 0.0f), {0.0f, 1.0f, 0.0f}); + lightManager.AddDirectional(vec3(0.0f, -1.0f, 0.0f), {0.0f, 0.7f, 0.0f}); lightManager.AddPoint(vec3{2.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 15.0f); lightManager.AddPoint(vec3{-2.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, 15.0f); diff --git a/samples/03_model_render/shader/bindless_structs.hlsli b/samples/03_model_render/shader/bindless_structs.hlsli index 5124762..f974761 100644 --- a/samples/03_model_render/shader/bindless_structs.hlsli +++ b/samples/03_model_render/shader/bindless_structs.hlsli @@ -34,7 +34,7 @@ struct Block uint NodeBufferHandle; uint LightHandle; uint PointLightIndexer; - uint DirectionLightIndexer; + uint DirectionalLightIndexer; int MaterialIdx; uint NodeIdx; }; diff --git a/samples/03_model_render/shader/model.ps.hlsl b/samples/03_model_render/shader/model.ps.hlsl index 9da9149..8354f46 100644 --- a/samples/03_model_render/shader/model.ps.hlsl +++ b/samples/03_model_render/shader/model.ps.hlsl @@ -100,6 +100,33 @@ float3 FresnelSchlick(float cosine, float3 F_0) return F_0 + (1.0f - F_0) * pow(clamp(1.0f - cosine, 0.0f, 1.0f), 5.0f); // Clamp to avoid artifacts. } +float3 GetPBRContrib(float3 Albedo, float3 LightColor, float3 ViewDir, float3 Normal, float Metallic, float Roughness, float3 F_0, float3 LightDir, float LightDistance) +{ + float Attenuation = 1.0f / (LightDistance * LightDistance); // TODO: Controlled Attenuation + float3 Halfway = normalize(ViewDir + LightDir); + + float CosineFactor = max(dot(Halfway, ViewDir), 0.0f); + float NdotV = max(dot(Normal, ViewDir), 0.0f); + float NdotL = max(dot(Normal, LightDir), 0.0f); + + float3 Radiance = LightColor * Attenuation; + + float NormalDistribution = TrowbridgeReitzGGX(Normal, Halfway, Roughness); + float Geometry = GeometrySmith(NdotV, NdotL, Roughness); + float3 Fresnel = FresnelSchlick(CosineFactor, F_0); + + float3 Numerator = (NormalDistribution * Geometry) * Fresnel; + float Denominator = 4.0f * NdotV * NdotL; + float3 Specular = Numerator / max(Denominator, 0.00001); + + float3 K_Specular = Fresnel; + float3 K_Diffuse = 1.0f.xxx - K_Specular; + + K_Diffuse *= 1.0f - Metallic; + + return NdotL * Radiance * ((K_Diffuse * Albedo / PI) + Specular); +} + float3 GetPointLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal) { if (PushConstant.LightHandle == INVALID_HANDLE) @@ -117,7 +144,7 @@ float3 GetPointLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, // TODO: Cite float3 F_0 = 0.04f.xxx; F_0 = lerp(F_0, Albedo, Metallic); - float3 LightAmp = float3(23.47f, 21.31f, 20.79f); + float3 LightAmp = float3(23.47f, 21.31f, 20.79f); // TODO: Get rid float3 Contrib = 0.0f; for (uint i = 0; i < Count; ++i) @@ -141,30 +168,50 @@ float3 GetPointLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float B = (Light.Color & 0x0000FF00) >> 8; float3 LightColor = LightAmp * float3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255 + + Contrib += GetPBRContrib(Albedo, LightColor, ViewDir, Normal, Metallic, Roughness, F_0, LightDir, LightDistance); + } + + return Contrib; +} + + +float3 GetDirectionalLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal) +{ + if (PushConstant.LightHandle == INVALID_HANDLE) + return 0.0f.xxx; + + uint Count = IndexerCount(PushConstant.DirectionalLightIndexer); + + float3 ViewDir = normalize(Camera.Position.xyz - Position); + + float Metallic = MetalRough.r; + float Roughness = MetalRough.g; + + // Dielectric F_0 based on LearnOpenGL. + // TODO: Cite + float3 F_0 = 0.04f.xxx; + F_0 = lerp(F_0, Albedo, Metallic); + float3 LightAmp = float3(23.47f, 21.31f, 20.79f); // TODO: Get rid + + float3 Contrib = 0.0f; + for (uint i = 0; i < Count; ++i) + { + DirectionalLight Light = DirectionalLightBuffer[PushConstant.LightHandle][i]; - float Attenuation = 1.0f / (LightDistance * LightDistance); // TODO: Controlled Attenuation - float3 Halfway = normalize(ViewDir + LightDir); + if (Light.Validity_ < 0.0f) + continue; - float CosineFactor = max(dot(Halfway, ViewDir), 0.0f); - float NdotV = max(dot(Normal, ViewDir), 0.0f); - float NdotL = max(dot(Normal, LightDir), 0.0f); + float3 LightDir = -normalize(float3(Light.Direction)); - float3 Radiance = LightColor * Attenuation; + // Color Unpack + float R = (Light.Color & 0xFF000000) >> 24; + float G = (Light.Color & 0x00FF0000) >> 16; + float B = (Light.Color & 0x0000FF00) >> 8; - float NormalDistribution = TrowbridgeReitzGGX(Normal, Halfway, Roughness); - float Geometry = GeometrySmith(NdotV, NdotL, Roughness); - float3 Fresnel = FresnelSchlick(CosineFactor, F_0); - - float3 Numerator = (NormalDistribution * Geometry) * Fresnel; - float Denominator = 4.0f * NdotV * NdotL; - float3 Specular = Numerator / max(Denominator, 0.00001); - - float3 K_Specular = Fresnel; - float3 K_Diffuse = 1.0f.xxx - K_Specular; - - K_Diffuse *= 1.0f - Metallic; - - Contrib += NdotL * Radiance * ((K_Diffuse * Albedo / PI) + Specular); + float3 LightColor = LightAmp * float3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255 + + Contrib += GetPBRContrib(Albedo, LightColor, ViewDir, Normal, Metallic, Roughness, F_0, LightDir, 1.0f); } return Contrib; @@ -203,7 +250,7 @@ FS_Output main(FS_Input StageInput) float Alpha = AlbedoAlpha.a; float2 MetalRough = GetMetalRough(StageInput.InUV0); float3 Emission = GetEmissive(StageInput.InUV0); - float3 Color = /*GetDirectionalLightInfluence(Albedo, MetalRough, Position, Normal) +*/ GetPointLightInfluence(Albedo, MetalRough, Position, Normal); + float3 Color = GetDirectionalLightInfluence(Albedo, MetalRough, Position, Normal) + GetPointLightInfluence(Albedo, MetalRough, Position, Normal); Output.ColorTarget = float4(Uncharted2Tonemap(Color + Emission), Alpha); return Output;