mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 07:49:19 +02:00
122 lines
4.2 KiB
HLSL
122 lines
4.2 KiB
HLSL
#ifndef LIGHTING_FUNCTIONS_HLSLI
|
|
#define LIGHTING_FUNCTIONS_HLSLI
|
|
|
|
struct SurfaceData {
|
|
float3 m_Albedo;
|
|
float m_Alpha;
|
|
float m_Metalness;
|
|
float m_Roughness;
|
|
float m_DiffuseOcclusion;
|
|
float m_SpecularOcclusion;
|
|
float3 m_View;
|
|
float3 m_Normal;
|
|
float3 m_Reflect;
|
|
float m_NdotV;
|
|
float3 m_SpecularF0;
|
|
float3 m_SpecularF;
|
|
float m_HorizonFading;
|
|
};
|
|
|
|
struct DirectionalLight {
|
|
float3 m_LightVector;
|
|
float3 m_Color;
|
|
};
|
|
|
|
void ApplyDirectionalLight(inout float3 lit, in DirectionalLight light, in SurfaceData material, in float shadow);
|
|
|
|
float3 FresnelSchlickRoughness(float cosTheta, float3 F0, float roughness);
|
|
float FresnelSchlickRoughness(float cosTheta, float F0, float roughness);
|
|
float DistributionGGX(float3 N, float3 H, float roughness);
|
|
float GeometrySchlickGGX(float NdotV, float roughness);
|
|
float GeometrySmith(float3 N, float3 V, float3 L, float roughness);
|
|
float ComputeSpecOcclusion(float NdotV, float AO, float roughness);
|
|
float HorizonFading(float NdotL, float horizonFade);
|
|
|
|
void ApplyDirectionalLight(inout float3 lit, in DirectionalLight light, in SurfaceData material, in float shadow) {
|
|
float3 H = normalize(material.m_View + light.m_LightVector);
|
|
float3 radiance = light.m_Color;
|
|
|
|
float NdotL = max(dot(material.m_Normal, light.m_LightVector), 0.);
|
|
|
|
// Cook-Torrance BRDF
|
|
float NDF = DistributionGGX(material.m_Normal, H, material.m_Roughness);
|
|
float G = GeometrySmith(material.m_Normal, material.m_View, light.m_LightVector, material.m_Roughness);
|
|
|
|
float3 numerator = NDF * G * material.m_SpecularF;
|
|
float denominator = 4. * material.m_NdotV * NdotL + 1e-4; // + 0.0001 to prevent divide by zero
|
|
float3 specular = numerator / denominator;
|
|
|
|
// kS is equal to Fresnel
|
|
float3 kS = material.m_SpecularF;
|
|
// for energy conservation, the diffuse and specular light can't
|
|
// be above 1.0 (unless the surface emits light); to preserve this
|
|
// relationship the diffuse component (kD) should equal 1.0 - kS.
|
|
float3 kD = 1. - kS;
|
|
// multiply kD by the inverse metalness such that only non-metals
|
|
// have diffuse lighting, or a linear blend if partly metal (pure metals
|
|
// have no diffuse light).
|
|
kD = lerp(kD, 0., material.m_Metalness);
|
|
|
|
|
|
// add to outgoing radiance Lo
|
|
//lit += shadow * (kD * material.m_Albedo * ONE_OVER_PI * material.m_DiffuseOcclusion * material.m_Alpha + specular * material.m_SpecularOcclusion * HorizonFading(NdotL, material.m_HorizonFading)) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
|
|
lit += shadow * (kD * material.m_Albedo * ONE_OVER_PI * material.m_Alpha + specular * HorizonFading(NdotL, material.m_HorizonFading)) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
|
|
}
|
|
|
|
float FresnelSchlickRoughness(float cosTheta, float F0, float roughness)
|
|
{
|
|
return F0 + (max(1. - roughness, F0) - F0) * pow(saturate(1. - cosTheta), 5.);
|
|
}
|
|
|
|
float3 FresnelSchlickRoughness(float cosTheta, float3 F0, float roughness)
|
|
{
|
|
return F0 + (max((float3)(1. - roughness), F0) - F0) * pow(saturate(1. - cosTheta), 5.);
|
|
}
|
|
|
|
float DistributionGGX(float3 N, float3 H, float roughness)
|
|
{
|
|
float a = roughness*roughness;
|
|
float a2 = a*a;
|
|
float NdotH = max(dot(N, H), 0.);
|
|
float NdotH2 = NdotH*NdotH;
|
|
|
|
float num = a2;
|
|
float denom = (NdotH2 * (a2 - 1.) + 1.);
|
|
denom = PI * denom * denom;
|
|
|
|
return num / denom;
|
|
}
|
|
|
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
|
{
|
|
float r = (roughness + 1.);
|
|
float k = (r*r) / 8.;
|
|
|
|
float num = NdotV;
|
|
float denom = NdotV * (1. - k) + k;
|
|
|
|
return num / denom;
|
|
}
|
|
|
|
float GeometrySmith(float3 N, float3 V, float3 L, float roughness)
|
|
{
|
|
float NdotV = max(dot(N, V), 0.);
|
|
float NdotL = max(dot(N, L), 0.);
|
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
|
|
|
return ggx1 * ggx2;
|
|
}
|
|
|
|
float ComputeSpecOcclusion(float NdotV, float AO, float roughness)
|
|
{
|
|
return saturate(pow(NdotV + AO, exp2(-16. * roughness - 1.)) - 1. + AO);
|
|
}
|
|
|
|
float HorizonFading(float NdotL, float horizonFade)
|
|
{
|
|
float horiz = saturate(1.0 + horizonFade * NdotL);
|
|
return horiz * horiz;
|
|
}
|
|
|
|
#endif |