Hi all,

My renderer currently has PBR shading and shadow maps for one directional light. Now I want to add shadows for point lights as well. The shadows I have so far are based on the examples provided by kosmonautgames in this thread and it’s working great.

For the point lights I have generated cube maps for each light, but I’m just struggling with how to now apply those cube maps. I know it’s similar to what I have for the directional light, I think I just need a bit more code to calculate which face of the cube map to use.

Here’s the relevant parts of my shader: the function that calculates the shadows, and the lighting for the direcitonal and point lights. You can see how I have the shadows working for the directional light already, just not sure how to modify that to use a cube map for the point lights.

``````//----------------------------------------------------------------------------------
// Calculates the shadow term using PCF
//----------------------------------------------------------------------------------
{

float variableBias = clamp(0.001 * tan(acos(ndotl)), 0, _DepthBias);

//safe to assume it's a square
float size = 1 / _ShadowMapSize;

float samples[4];

shadow_term = (samples[0] + samples[1] + samples[2] + samples[3]) / 4.0;

}

//----------------------------------------------------------------------------------
// Lights
//----------------------------------------------------------------------------------
float3 CalculatePointLights(float3 worldPosition, float3 N, float3 albedo, float metallic, float roughness)
{
float3 V = normalize(_CameraPos - worldPosition);

//Calculate surface reflection at zero incidence, default to 0.04 but adjust for metallic surfaces.
float3 F0 = float3(0.04, 0.04, 0.04);
F0 = lerp(F0, albedo, metallic);

//Reflection equation
float3 Lo = float3(0.0, 0.0, 0.0);
for(int i = 0; i < MaxPointLights; ++i)
{
float3 L = normalize(_PointLightPos[i] - worldPosition);
float3 H = normalize(V + L);
float distance = length(_PointLightPos[i] - worldPosition);
float attenuation = _PointLightRange[i] / (distance * distance);
float3 radiance = _PointLightColors[i] * attenuation * _PointLightIntensity[i];

// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
float3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);

float3 kS = F;
float3 kD = float3(1.0, 1.0, 1.0) - kS;
kD *= 1.0 - metallic;

float3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0);
float3 specular = numerator / max(denominator, 0.001);

float NdotL = max(dot(N, L), 0.0);

//_PointLightSpaceMatrix: Array of 6 view projection matrices for the point light

Lo += (kD * albedo / PI + specular) * radiance * NdotL * shadowContribution;
}
return Lo;
}

float3 CalculateDirectionalLights(float3 worldPosition, float3 N, float3 albedo, float metallic, float roughness)
{
float3 V = normalize(_CameraPos - worldPosition);

//Calculate surface reflection at zero incidence, default to 0.04 but adjust for metallic surfaces.
float3 F0 = float3(0.04, 0.04, 0.04);
F0 = lerp(F0, albedo, metallic);

//Reflection equation
float3 Lo = float3(0.0, 0.0, 0.0);
for(int i = 0; i < MaxDirectionalLights; ++i)
{
float3 L = -_DirectionalLights[i];
float3 H = normalize(V + L);
float3 radiance = _DirectionalColors[i] * _DirectionalIntensity[i];

// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
float3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);

float3 kS = F;
float3 kD = float3(1.0, 1.0, 1.0) - kS;
kD *= 1.0 - metallic;

float3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0);
float3 specular = numerator / max(denominator, 0.001);

float NdotL = max(dot(N, L), 0.0);

{
float4 lightingPosition = mul(float4(worldPosition, 1), _LightSpaceMatrix);