Hi,
I encountered an issue I can’t really understand so I’ll try to explain it here to get a reasonable explanation of what’s happing. I modified the tiled deferred rendering code by Andrew Lauritzen (http://software.intel.com/en-us/articles/deferred-rendering-for-current-and-future-rendering-pipelines) to have shadows maps for each light. To be able to turn on and off shadows I’m using shader classes that look this:
interface iBaseVPLShadow
{
bool IsEnabled();
float GetVisibility(Texture2DArray shadowBuffer, float3 receiverWorldPos, float4x4 lightViewProjection, uint lightIndex);
};
The lighting is done in a compute shader. Basically like this:
#define TILE_DIM 8
[numthreads(TILE_DIM, TILE_DIM, 1)]
void main( … )
{
// Read GBuffer at current Texel
// Calculate Tile Frustum
GroupMemoryBarrierWithGroupSync();
for all lights
{
// each thread of the block culls one light
// if the light intersects the tile frustum add it to the tiles light list
}
GroupMemoryBarrierWithGroupSync();
float3 luminance = float3(0,0,0);
for all lights in the tiles light list
{
// shadow test
float visibility = 1.0;
if (SlotVPLShadow.IsEnabled())
visibility = SlotVPLShadow.GetVisibility(VPLShadowBuffer, worldPosition, VPLViewProjectionData[tileLightIndex], tileLightIndex);
// light amount of the light arriving at the surface
float3 irradiance = visibility * SlotVPL.GetIrradiance( … )
// light amount reflected by the surface (visible to the observer)
luminance += irradiance * SlotDiffuseMaterial.BRDF( … )
}
// write luminance to output target
}
As stated by that pseudo code I’m using multiple interface. One class to describe the light source, one for the material brdf, and one for the shadows. I implemented the iBaseVPLShadow interface to do a common shadow mapping with a Load in the shadow buffer and a comparison in light space depth. And I also implemented the interface for “no shadows” in which case the GetVisibility(…) method simply returns 1.0.
Now to the interesting part.
You may ask yourself why there is the IsEnabled() method. Actually I really don’t know^^ But if it is not there the execution time for the “no shadow” class is HIGHER than the “shadow mapping” class by factor 1.5. And there are shadow artifacts if don’t unroll the last loop in the latter case.
I think both problems might be related to the loop because it’s not clear how often to loop at compile time and number of lights easily goes beyond 100. But nevertheless it totally confuses my understanding on how shader classes work because everything is totally fine (and fast) with the IsEnabled() check to prevent the GetVisibility() call if the shadows are disabled.
Sorry for this vague description but I'm not able provide a mini sample because it's in a bigger system with lots of dependencies.