when I run my program with vec3(0.99999, 1.0, 1.0) it works as I intended (When an object lies within a shadowmap I will render with shadow information, else it will multiply the final color with effectively vec3(1.0, 1.0, 1.0)).
However, if I run the code with vec3(1.0, 1.0, 1.0) everything including the valid shadow information gets white except some few little weird artifacts.
Also, this issue doesn’t happen when I run it on a VirtualBox Lubuntu.
My machine:
A few other suggestions (likely not related to your problem):
I doubt you want to chose the split based on radial distance (on world space). More likely you want eye-space Z distance.
Until you get this solidly debugged, I’d recommend that you disable anisotropic filtering on your shadow map texture if it is on. Your code currently does not provide reasonable derivatives for shadow texture lookup on split boundaries (for multiple reasons), and you’re going to want to fix those if/when you enable anisotropic filtering.
Finally, check that you have a min filter set on the texture that doesn’t use MIPmaps (e.g.GL_LINEAR or GL_NEAREST). You’ve probably got this set right already though. MIPmap texture filtering is one other feature that will go nuts if your texcoord derivatives are nonsense.
And it works. However, it seems like it is slower. I don’t have a good idea, how costly a texture lookup is, but i guess the reason for the slowdown is that i always access all textures. Is there a way to make this more efficient without changing the fundamental design?
I doubt you want to choose the split based on radial distance (on world space). More likely you want eye-space Z distance.
Yes, what i had was not really accurate but because currently in my shaders the camera is always at 0,0,0 (basically frag_position_world_space is really already in camera space, maybe bad var-naming) it doesn’t matter too much. i changed it a little bit so that it is indeed just the z value which makes more sense regarding the creation of the shadow maps.
I didn’t understand the point with the derivatives completely, is this important even if I don’t use anisotropic filtering?
It matters for anisotropic filtering and for MIPmap selection. Both of these require scale factors which are normally derived from the partial derivatives of the texture coordinates with respect to screen-space X and Y. Specifically, the GLSL texture() function finds the derivatives of the supplied texture coordinates and uses these to calculate the scale factors. But derivatives aren’t defined within non-uniform control flow.
You can get around the problem by using the textureGrad() function which accepts derivatives as separate arguments. You can compute the derivatives outside of the conditional and pass them in. E.g. rather than calling directional_shadow_calculation (which both computes the coordinates and performs the texture lookup) in the loop, you only need to calculate the coordinates for each cascade, calculate the derivatives for each cascade (using dFdx and dFdy), then perform the texture lookup only for the cascade being used. You have to calculate the derivatives for each cascade because dFdx and dFdy can’t be used within non-uniform control flow.
Also, if you know that the texture coordinates for different cascades differ only by an affine transformation, you could calculate the derivatives for one set of texture coordinates and transform the derivatives accordingly.
Ok, if I understood correctly, then it doesn’t matter if I do a texture lookup in non-uniform-flow-control if I use textureGrad(depth_map, shadows_coords[i], d_x[i], d_y[i]) (with shadows_coords[i], d_x[i], d_y[i] caculated at the begin of the shader in uniform-flow-control)?
I tried now this code, which implements this idea, but I get some random noise again if I run this:
The last post mentions some of the solutions I found, which I’ll just re-iterate here. Either:
Tweak the split indices in the shader so that pixels in the same GPU pixel quad always use the same split.
Compute analytic texcoord gradients in the shader.
Both are described in:
Shader X7, Chapter 4.1 (Practical Cascaded Shadow Maps), “Filtering Across Splits” section, pp. 321-327
…but the code they list for #1 (derived from a snippet by Andrew Lauritzen) is buggy.
You can find the correct, original snippet here:
Variance Shadow Maps Demo (D3D10) (Andrew Lauritzen, Beyond3D post, 4/25/07)
Use log2 or his lookup table as desired. Also the dot trick for computing the split saves a surprisingly number of frag instructions.
I ended up using this (i.e. solution #1). It’s a pretty slick trick, and it works well.
It definitely matters for MIPmap filtering and anisotropic texture filtering. However even if those are disabled (and you probably want them both disabled here), since texture() makes use of derivatives (gradiants), and in this case the gradiants are undefined, intuitively it could result in the texture lookup results being undefined as well depending on how the lookup is performed. The spec may explicitly define this case as undefined or not; haven’t checked.