Files
maszyna/betterRenderer/shaders/manul/lighting.hlsli
2025-12-22 21:43:52 +01:00

148 lines
6.0 KiB
HLSL

#ifndef LIGHTING_HLSLI
#define LIGHTING_HLSLI
#include "math.hlsli"
#include "material_common.hlsli"
#include "sky_common.hlsli" // ray_sphere_intersection
#include "view_data.hlsli"
#include "lighting_functions.hlsli"
#include "forward_plus/light.hlsli"
SamplerState g_SamplerLinearClamp : register(s8);
TextureCube<float3> g_DiffuseEnvmap : register(t8);
TextureCube<float3> g_SpecularEnvmap : register(t9);
Texture2D<float2> g_BrdfLUT : register(t10);
Texture2D<float4> g_CloudShadowMap : register(t15);
Texture2D<uint2> g_LightGrid : register(t16);
StructuredBuffer<uint> g_LightIndexBuffer : register(t17);
StructuredBuffer<PackedLight> g_LightBuffer : register(t18);
#define LIGHTING_NEEDS_PIXELPOSITION 1
#if LIGHTING_NEEDS_PIXELPOSITION
void ApplyMaterialLighting(out float4 lit, in MaterialData material, in uint2 pixel_position);
#else
void ApplyMaterialLighting(out float4 lit, in MaterialData material);
#endif
void ApplyIBL(inout float3 lit, in SurfaceData material);
void ApplyForwardPlus(inout float3 lit, in SurfaceData material, in float3 position, in uint2 pixel_position);
#if LIGHTING_NEEDS_PIXELPOSITION
void ApplyMaterialLighting(out float4 lit, in MaterialData material, in uint2 pixel_position)
#else
void ApplyMaterialLighting(out float4 lit, in MaterialData material)
#endif
{
// Camera-centric world position
float3 view = mul((float3x3)g_InverseModelView, material.m_Position);
#ifdef GBUFFER_SSAO_HLSLI
float4 bent_normal = GetBentNormal(pixel_position);
bent_normal.a = min(material.m_MaterialParams.b, bent_normal.a);
bent_normal.xyz = mul((float3x3)g_InverseModelView, bent_normal.xyz);
#endif
// Convert material to surface data
SurfaceData surface_data;
surface_data.m_Albedo = saturate(material.m_MaterialAlbedoAlpha.rgb);
surface_data.m_Alpha = material.m_MaterialAlbedoAlpha.a;
surface_data.m_Metalness = material.m_MaterialParams.r;
surface_data.m_Roughness = material.m_MaterialParams.g;
#ifdef GBUFFER_SSAO_HLSLI
surface_data.m_DiffuseOcclusion = bent_normal.a;
#else
surface_data.m_DiffuseOcclusion = material.m_MaterialParams.b;
#endif
surface_data.m_Normal = mul((float3x3)g_InverseModelView, material.m_MaterialNormal);
surface_data.m_View = -normalize(view);
surface_data.m_Reflect = reflect(-surface_data.m_View, surface_data.m_Normal);
surface_data.m_NdotV = max(dot(surface_data.m_Normal, surface_data.m_View), 0.);
surface_data.m_SpecularF0 = float3(.04, .04, .04) * material.m_MaterialParams.a * 2.;
surface_data.m_SpecularF0 = lerp(surface_data.m_SpecularF0, surface_data.m_Albedo, surface_data.m_Metalness);
surface_data.m_SpecularF = FresnelSchlickRoughness(surface_data.m_NdotV, surface_data.m_SpecularF0, surface_data.m_Roughness);
surface_data.m_HorizonFading = 1.6;
#ifdef GBUFFER_SSAO_HLSLI
float BNdotR = max(0., dot(surface_data.m_Reflect, bent_normal.xyz));
surface_data.m_SpecularOcclusion = ComputeSpecOcclusion(BNdotR, surface_data.m_DiffuseOcclusion, surface_data.m_Roughness);
#else
surface_data.m_SpecularOcclusion = ComputeSpecOcclusion(surface_data.m_NdotV, surface_data.m_DiffuseOcclusion, surface_data.m_Roughness);
#endif
lit.rgb = material.m_MaterialEmission * surface_data.m_Alpha;
lit.a = 1. - (saturate((1. - surface_data.m_Alpha) * lerp(1. - dot(surface_data.m_SpecularF, 1./3.), 0., surface_data.m_Metalness)));
float shadow = 1.;
#ifdef SHADOW_HLSLI
shadow = GetShadow(view, material);
#endif
#ifdef GBUFFER_CONTACT_SHADOWS_HLSLI
shadow = min(shadow, GetContactShadows(pixel_position));
#endif
float t = ray_sphere_intersection(view, g_LightDir.xyz, 10000.);
if(t >= 0.) {
float3 cloud_dir = normalize(view + g_LightDir.xyz * t);
cloud_dir.y = 4. * abs(cloud_dir.y);
cloud_dir = normalize(cloud_dir);
float4 cloud_mask = g_CloudShadowMap.SampleLevel(g_SamplerLinearClamp, cloud_dir.xz * .5 + .5, 0.);
shadow = min(shadow, 1. - cloud_mask.a * .6);
}
// Apply IBL cubemap
ApplyIBL(lit.rgb, surface_data);
// Apply directional light
DirectionalLight directionalLight;
directionalLight.m_LightVector = g_LightDir.xyz;
directionalLight.m_Color = g_LightColor.rgb;
ApplyDirectionalLight(lit.rgb, directionalLight, surface_data, shadow);
ApplyForwardPlus(lit.rgb, surface_data, view, pixel_position);
}
void ApplyIBL(inout float3 lit, in SurfaceData material) {
float3 kS = material.m_SpecularF;
float3 kD = 1. - kS;
kD = lerp(kD, 0., material.m_Metalness);
float2 brdf = g_BrdfLUT.SampleLevel(g_SamplerLinearClamp, float2(material.m_NdotV, material.m_Roughness), 0.);
lit += material.m_Albedo * kD * g_DiffuseEnvmap.SampleLevel(g_SamplerLinearClamp, material.m_Normal, 0.) * material.m_DiffuseOcclusion * material.m_Alpha;
lit += g_SpecularEnvmap.SampleLevel(g_SamplerLinearClamp, material.m_Reflect, sqrt(material.m_Roughness) * 5.) * (material.m_SpecularF * brdf.xxx + brdf.yyy) * material.m_SpecularOcclusion * HorizonFading(material.m_NdotV, material.m_HorizonFading);
}
void ApplyForwardPlus(inout float3 lit, in SurfaceData material, in float3 position, in uint2 pixel_position) {
uint2 light_range = g_LightGrid[pixel_position / 8];
for(int i = 0; i < light_range.y; ++i) {
Light light = UnpackLight(g_LightBuffer[g_LightIndexBuffer[light_range.x + i]]);
float3 L_offset = light.m_origin - position;
float L_dist_sqr = dot(L_offset, L_offset);
float3 L_dir = normalize(L_offset);
//lit += light.m_color;
if(L_dist_sqr > light.m_radius * light.m_radius) continue;
float cos_point_deviation = dot(-L_dir, light.m_direction);
if(light.m_cos_outer > -1.5 && cos_point_deviation < light.m_cos_outer) continue;
float cone = light.m_cos_outer > -1.5 ? saturate((cos_point_deviation - light.m_cos_inner) / (light.m_cos_outer - light.m_cos_inner)) : 0.;
float attenuation = 1. / dot(L_offset, L_offset) * (1. - cone);
DirectionalLight directionalLight;
directionalLight.m_LightVector = L_dir;
directionalLight.m_Color = light.m_color * attenuation;
ApplyDirectionalLight(lit.rgb, directionalLight, material, 1.);
}
}
#endif