I have been working with this ES extension for a while, but I still don't quite get what these shadows samplers are and what one could use them for. Googling didn't really get me any nice, readable results, so I am posting here.
I am looking for something that would help me to really grok what these could do. This can be either real-life use case or something that would just show how these are different from normal samplers. I mean, okey, they store depth data. But how is that data generated? Is it just made from a texture bound to a depth attachment?
Also, my question applies to both DT (desktop) GL and ES, and possibly to WebGL too; I don't really care about the exact calls or enumerations, since they are easily found in specs.
A Sampler Object is an OpenGL Object that stores the sampling parameters for a Texture access inside of a shader.
Shader stages: A sampler is a set of GLSL variable types. Variables of one of the sampler types must be uniforms or as function parameters. Each sampler in a program represents a single texture of a particular texture type. The type of the sampler corresponds to the type of the texture that can be used by that sampler.
The idea behind shadow mapping is quite simple: we render the scene from the light's point of view and everything we see from the light's perspective is lit and everything we can't see must be in shadow. Imagine a floor section with a large box between itself and a light source.
If you looked out from a source of light, all of the objects you can see would appear in light. Anything behind those objects, however, would be in shadow. This is the basic principle used to create a shadow map. The light's view is rendered, storing the depth of every surface it sees (the shadow map).
A "shadow sampler" is a sampler that is used for depth comparison textures. Normally, if you access a depth texture, you get the (filtered) depth value at that texture coordinate. With depth comparison mode however, what you're doing is a different operation.
For each sample fetched from the texture, you compare the depth with a given value. If the comparison passes, then the sample fetched is effectively 1.0. If the comparison fails, it is 0.0. Filtering then works on the samples after this comparison. So if I'm doing linear filtering, and half the samples pass the compare and half don't, the value I get is 0.5.
To do this, you must both activate depth comparison on the sampler object/texture object you're using, but you also must use a shadow sampler in the shader. The reason for this is that the texture accessing function now needs to take an extra value: the value to compare the texture access against.
This is primarily used for shadow maps, hence the name. Shadow maps store the depth from the light to the nearest surface. Therefore, you compare it to the depth from the light to the surface being rendered. If the surface being rendered is closer to the light than what's in the shadow map, then you get 1.0 from the shadow sampler. If the surface is farther from the light, you get 0.0. In either case, you multiply the value by the light color, then do all your lighting computations for that light as normal.
The reason for the comparison before the sampling is something called "Percentage Closer Filtering". Filtering between the depth values doesn't produce reasonable results; it's not what you want. You want to do the comparison first, then filter the compared boolean results. What you then get is a measurement of how many samples from the depth texture passed the comparison. This gives better results along the edges of shadows.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With