DaveH355 / clustered-shading

An OpenGL tutorial on clustered shading. A technique for efficiently rendering thousands of dyanmic lights in games.
MIT License
32 stars 2 forks source link

Lights breaking when the camera is too close or too far away #5

Open Ravbug opened 1 month ago

Ravbug commented 1 month ago

Looks like I still have a couple bugs to iron out in my implementation of clustered-forward after #4.

The system appears to work correctly, unless the camera is moved very close to the light, or far away from it.

https://github.com/user-attachments/assets/a17bd6b9-6559-4215-9347-29daeb813759

This is what the computed cluster coordinates look like when I move the camera around:

https://github.com/user-attachments/assets/a60ded34-a292-4c07-bccb-8dac3c34458a

In the close-up case, it appears to have calculated the distance to the closest point in the cluster as around 14, which seems wrong considering that tile should be right next to the center of the light.

image

It's a similar story for the far away case -- I chose a pixel right next to the center of the light and it computed a distance of around 14.

image

Do you have any thoughts about what could be causing this?

DaveH355 commented 1 month ago

It's hard to say what could be the problem. I have not seen this before so it may just be an implementation bug. Although it's interesting, your close-up case shows a close light tested against far away AABB your far case is a far light against a close AABB

Ravbug commented 1 month ago

In the grid building shader, I flipped Znear and Zfar, and that seems to have fixed the errors when the camera is very close to the light (the issue where the lights disappear as the camera moves far away still occurs)

image

Does this make sense as a fix for that issue? Or am I gaslighting myself

Ravbug commented 1 month ago

Changing the zNear at the beginning of both statements appears to have fixed the issue with lights at a distance:

image
DaveH355 commented 1 month ago

Ah my bad, I may have been wrong from before. Since you're using reverse Z, the near plane is probably 1 in ndc space. So revert the changes to tileNear and tileFar

The screenToView function in the cluster building shader should be

vec3 screenToView(vec2 screenCoord)
{
    // normalize screenCoord to [-1, 1] 
    // z = 1.0 (near plane in reverse z) 
    // w = 1.0
    vec4 ndc = vec4(screenCoord / screenDimensions * 2.0 - 1.0, 1.0, 1.0);

    vec4 viewCoord = inverseProjection * ndc;
    viewCoord /= viewCoord.w;
    return viewCoord.xyz;
}
Ravbug commented 1 month ago

Unfortunately reverting the changes to tileNear and tileFar and using this updated screenToView function brings back both the near and far cluster bugs.

DaveH355 commented 1 month ago

Are you sure your Uniform Buffer Object is layed out correctly? This from your cluster_build_grid.csh

layout(push_constant, scalar) uniform UniformBufferObject{
    mat4 inverseProjection;
    uvec3 gridSize;
    float zNear;
    uvec2 screenDimensions;
    float zFar;
} ubo;

Storing a vec3 won't work as expected in UBOs See https://stackoverflow.com/questions/38172696/should-i-ever-use-a-vec3-inside-of-a-uniform-buffer-or-shader-storage-buffer-o

EDIT: nevermind, that only applies to std140/std430