|
|
@@ -118,12 +118,12 @@ void main()
|
|
|
shadowFactor = 1.0;
|
|
|
}
|
|
|
|
|
|
- Vec3 l = -u_dirLight.m_dir;
|
|
|
+ const Vec3 l = -u_dirLight.m_dir;
|
|
|
|
|
|
- F32 lambert = max(gbuffer.m_subsurface, dot(l, gbuffer.m_normal));
|
|
|
+ const F32 lambert = max(gbuffer.m_subsurface, dot(l, gbuffer.m_normal));
|
|
|
|
|
|
- Vec3 diffC = diffuseLambert(gbuffer.m_diffuse);
|
|
|
- Vec3 specC = computeSpecularColorBrdf(gbuffer, viewDir, l);
|
|
|
+ const Vec3 diffC = diffuseLambert(gbuffer.m_diffuse);
|
|
|
+ const Vec3 specC = computeSpecularColorBrdf(gbuffer, viewDir, l);
|
|
|
|
|
|
out_color += (diffC + specC) * u_dirLight.m_diffuseColor * (shadowFactor * lambert);
|
|
|
}
|
|
|
@@ -138,7 +138,7 @@ void main()
|
|
|
|
|
|
ANKI_BRANCH if(light.m_shadowAtlasTileScale >= 0.0)
|
|
|
{
|
|
|
- F32 shadow = computeShadowFactorPointLight(light, frag2Light, u_shadowTex, u_trilinearClampSampler);
|
|
|
+ const F32 shadow = computeShadowFactorPointLight(light, frag2Light, u_shadowTex, u_trilinearClampSampler);
|
|
|
lambert *= shadow;
|
|
|
}
|
|
|
|
|
|
@@ -152,12 +152,12 @@ void main()
|
|
|
|
|
|
LIGHTING_COMMON_BRDF();
|
|
|
|
|
|
- F32 spot = computeSpotFactor(l, light.m_outerCos, light.m_innerCos, light.m_dir);
|
|
|
+ const F32 spot = computeSpotFactor(l, light.m_outerCos, light.m_innerCos, light.m_dir);
|
|
|
|
|
|
- F32 shadowmapLayerIdx = light.m_shadowmapId;
|
|
|
+ const F32 shadowmapLayerIdx = light.m_shadowmapId;
|
|
|
ANKI_BRANCH if(shadowmapLayerIdx >= 0.0)
|
|
|
{
|
|
|
- F32 shadow = computeShadowFactorSpotLight(light, worldPos, u_shadowTex, u_trilinearClampSampler);
|
|
|
+ const F32 shadow = computeShadowFactorSpotLight(light, worldPos, u_shadowTex, u_trilinearClampSampler);
|
|
|
lambert *= shadow;
|
|
|
}
|
|
|
|
|
|
@@ -171,67 +171,100 @@ void main()
|
|
|
|
|
|
const Vec3 reflDir = reflect(-viewDir, gbuffer.m_normal);
|
|
|
const F32 reflLod = F32(IR_MIPMAP_COUNT - 1u) * gbuffer.m_roughness;
|
|
|
- F32 totalBlendWeight = EPSILON;
|
|
|
|
|
|
- // Loop probes
|
|
|
- ANKI_LOOP while((idx = u_lightIndices[idxOffset++]) != MAX_U32)
|
|
|
+ if(subgroupAll(u_lightIndices[idxOffset] != MAX_U32 && u_lightIndices[idxOffset + 1u] == MAX_U32))
|
|
|
{
|
|
|
- const ReflectionProbe probe = u_reflectionProbes[idx];
|
|
|
- const Vec3 aabbMin = probe.m_aabbMin;
|
|
|
- const Vec3 aabbMax = probe.m_aabbMax;
|
|
|
- const Vec3 probeOrigin = probe.m_position;
|
|
|
- const F32 cubemapIndex = probe.m_cubemapIndex;
|
|
|
-
|
|
|
- // Compute blend weight
|
|
|
- const F32 blendWeight = computeProbeBlendWeight(worldPos, aabbMin, aabbMax, 0.2);
|
|
|
- totalBlendWeight += blendWeight;
|
|
|
-
|
|
|
- // Sample reflections
|
|
|
- Vec3 cubeUv = intersectProbe(worldPos, reflDir, aabbMin, aabbMax, probeOrigin);
|
|
|
- Vec4 cubeArrUv = Vec4(cubeUv, cubemapIndex);
|
|
|
- Vec3 c = textureLod(u_reflectionsTex, u_trilinearClampSampler, cubeArrUv, reflLod).rgb;
|
|
|
- specIndirect += c * blendWeight;
|
|
|
+ // Only one probe, do a fast path without blend weight
|
|
|
+
|
|
|
+ const ReflectionProbe probe = u_reflectionProbes[u_lightIndices[idxOffset]];
|
|
|
+ idxOffset += 2u;
|
|
|
+
|
|
|
+ // Sample
|
|
|
+ const Vec3 cubeUv = intersectProbe(worldPos, reflDir, probe.m_aabbMin, probe.m_aabbMax, probe.m_position);
|
|
|
+ const Vec4 cubeArrUv = Vec4(cubeUv, probe.m_cubemapIndex);
|
|
|
+ specIndirect = textureLod(u_reflectionsTex, u_trilinearClampSampler, cubeArrUv, reflLod).rgb;
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Zero or more than one probes, do a slow path that blends them together
|
|
|
|
|
|
- // Normalize the colors
|
|
|
- specIndirect /= totalBlendWeight;
|
|
|
+ F32 totalBlendWeight = EPSILON;
|
|
|
+
|
|
|
+ // Loop probes
|
|
|
+ ANKI_LOOP while((idx = u_lightIndices[idxOffset++]) != MAX_U32)
|
|
|
+ {
|
|
|
+ const ReflectionProbe probe = u_reflectionProbes[idx];
|
|
|
+
|
|
|
+ // Compute blend weight
|
|
|
+ const F32 blendWeight = computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, 0.2);
|
|
|
+ totalBlendWeight += blendWeight;
|
|
|
+
|
|
|
+ // Sample reflections
|
|
|
+ const Vec3 cubeUv =
|
|
|
+ intersectProbe(worldPos, reflDir, probe.m_aabbMin, probe.m_aabbMax, probe.m_position);
|
|
|
+ const Vec4 cubeArrUv = Vec4(cubeUv, probe.m_cubemapIndex);
|
|
|
+ Vec3 c = textureLod(u_reflectionsTex, u_trilinearClampSampler, cubeArrUv, reflLod).rgb;
|
|
|
+ specIndirect += c * blendWeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Normalize the colors
|
|
|
+ specIndirect /= totalBlendWeight;
|
|
|
+ }
|
|
|
|
|
|
// Read the SSL result
|
|
|
const Vec4 ssr = textureLod(u_ssrRt, u_trilinearClampSampler, in_uv, 0.0);
|
|
|
|
|
|
// Combine the SSR and probe reflections and write the result
|
|
|
- const Vec3 finalRefl = specIndirect * ssr.a + ssr.rgb;
|
|
|
+ const Vec3 finalSpecIndirect = specIndirect * ssr.a + ssr.rgb;
|
|
|
|
|
|
// Compute env BRDF
|
|
|
const F32 NoV = max(EPSILON, dot(gbuffer.m_normal, viewDir));
|
|
|
const Vec3 env =
|
|
|
envBRDF(gbuffer.m_specular, gbuffer.m_roughness, u_integrationLut, u_trilinearClampSampler, NoV);
|
|
|
|
|
|
- out_color += finalRefl * env;
|
|
|
+ out_color += finalSpecIndirect * env;
|
|
|
}
|
|
|
|
|
|
// Indirect diffuse
|
|
|
{
|
|
|
Vec3 diffIndirect = Vec3(0.0);
|
|
|
- F32 totalBlendWeight = EPSILON;
|
|
|
|
|
|
- // Loop probes
|
|
|
- ANKI_LOOP while((idx = u_lightIndices[idxOffset++]) != MAX_U32)
|
|
|
+ if(subgroupAll(u_lightIndices[idxOffset] != MAX_U32 && u_lightIndices[idxOffset + 1u] == MAX_U32))
|
|
|
{
|
|
|
- GlobalIlluminationProbe probe = u_giProbes[idx];
|
|
|
+ // Only one probe, do a fast path without blend weight
|
|
|
|
|
|
- // Compute blend weight
|
|
|
- const F32 blendWeight = computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, 0.2);
|
|
|
- totalBlendWeight += blendWeight;
|
|
|
+ GlobalIlluminationProbe probe = u_giProbes[u_lightIndices[idxOffset]];
|
|
|
+ idxOffset += 2u;
|
|
|
|
|
|
// Sample
|
|
|
- const Vec3 c = sampleGlobalIllumination(
|
|
|
+ diffIndirect = sampleGlobalIllumination(
|
|
|
worldPos, gbuffer.m_normal, probe, u_globalIlluminationTextures, u_trilinearClampSampler);
|
|
|
- diffIndirect += c * blendWeight;
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Zero or more than one probes, do a slow path that blends them together
|
|
|
+
|
|
|
+ F32 totalBlendWeight = EPSILON;
|
|
|
|
|
|
- // Normalize
|
|
|
- diffIndirect /= totalBlendWeight;
|
|
|
+ // Loop probes
|
|
|
+ ANKI_LOOP while((idx = u_lightIndices[idxOffset++]) != MAX_U32)
|
|
|
+ {
|
|
|
+ GlobalIlluminationProbe probe = u_giProbes[idx];
|
|
|
+
|
|
|
+ // Compute blend weight
|
|
|
+ const F32 blendWeight =
|
|
|
+ computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, probe.m_fadeDistance);
|
|
|
+ totalBlendWeight += blendWeight;
|
|
|
+
|
|
|
+ // Sample
|
|
|
+ const Vec3 c = sampleGlobalIllumination(
|
|
|
+ worldPos, gbuffer.m_normal, probe, u_globalIlluminationTextures, u_trilinearClampSampler);
|
|
|
+ diffIndirect += c * blendWeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Normalize
|
|
|
+ diffIndirect /= totalBlendWeight;
|
|
|
+ }
|
|
|
|
|
|
out_color += diffIndirect * gbuffer.m_diffuse;
|
|
|
}
|