Article Index

Filtrage des lumières visibles

La première optimisation, consiste à diminuer le nombre de sources lumineuse global à prendre en compte, pour cela nous avons plusieurs informations à notre disposition. Premièrement grâce aux informations de la caméra, nous connaissons sont champs de vision, que l'ont peut modélisé par une pyramide (cf figure ci-dessous), c'est ce que l'on appelle le frustum. Ensuite nous avons différentes matrices pour passer entre les différents systèmes de coordonnés (scène, caméra, ...). Finalement nous connaissons la position de chaque lumières et sont rayon d'influence.

On peu donc faire un test de collision des lumières entre le frustum et la sphère d'influence de chaque lumières, si le test échoue, c'est que la lumière est en dehors du champ de vision. Sinon on stocke l'indice de la lumière dans une liste pour ne considéré que ces dernières plus tard (variable screenLights). Pour évité des calcules redondants dans les étapes suivantes, on peu sauvegarder quelques 'informations (ici NDCCoords de taille fixe) qui contient alors la position écran et le rayon d'influence de toutes les lumières visibles. Le code glsl ci-dessous en montre partiellement l'implémentation.

layoutscreenLights(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;

#include "ClusteredStruct.glsl"
#include "ClusteredCollision.glsl"
#include "ClusteredFrustum.glsl"

uniform mat4 projView;
uniform mat4 proj;
uniform mat4 view;

void main()
{
    vec4 frustum[6];
    FrustumFromMatrix(projView, frustum);
    
    vec4 worldLight = vec4(lightData[gl_GlobalInvocationID.x].pos4.xyz, 1);
    bool colliding = QuickSphereColliding(frustum, vec4(worldLight.xyz, lightData[gl_GlobalInvocationID.x].lightRadius));

    // If light affects any clusters on screen, send to next shader for allocation, 
    // else cull.
    
    if(colliding)
    {
        vec4 viewPos = projView * worldLight;
        vec4 ndcCoord = vec4(viewPos.xyz, lightData[gl_GlobalInvocationID.x].lightRadius);
        
        uint currentLightCount = atomicCounterIncrement(count);
        screenLights[currentLightCount] = int(gl_GlobalInvocationID.x);
        
        float w = 1.0f / viewPos.w;
        NDCCoords[currentLightCount] = ndcCoord * w;
    }
}