Reputation: 97
I'm using OpenGL 4.3 under GeForce GTX 750 to create Shadow Map. Right now the basic effect, shown as below, seems to be correct:
To erase the blocky-effect, I've tried to do a 2x2 PCF manually in the shader. It leads to the following result, which also seems to be correct:
For acceleration, I want to use the benefit provided by the graphics card, which gives the linear filter of the comparison result with one fetch. But the effect was different from the above one. It is more like OpenGL filters the rendering of the shadow linearly, but not filters on the Shadow Map:
Below it's how I do the hardware PCF:
I have noticed that the basic two things that have to be done in order to use the hardware PCF, which are:
shadow
type sampler, which in my case, is samplerCubeShadow
(I'm using a cube map type since I'm trying to create a point light scene).Set the comparison mode and filtering type, which in my case, is done by the following code:
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
After that, I use the texture
function in the shader like this (the reason that I use texture
but not textureProj
is because the latter doesn't seem to support cube map shadow texture since it will need a vec5
type which is obviously not supported yet):
vec4 posInLight4D = positionsInLight / positionsInLight.w; // divided by the 4-th component)
vec3 texCoord = GetCubeMapTexCoord(posInLight4D.xy); // get the texture coordinate in cube map texture. This can be assumed correct
float lightness = texture(shadowMapHardware, vec4(texCoord, posInLight4D.z));
But unfortunately, this gives the result shown in the third picture.
As far as I understand it, with the setting of the comparison mode and linear filter, the graphics card will do the comparison within a nearby 2x2 region and linearly interpolate the results and gives it back through the texture
function. I think I've done all the necessary parts, but I still cannot get the exact result shown in the 2nd picture.
Can anyone give me any suggestion about where I might go wrong? Thanks very much.
ps: The interesting thing is: I tried the textureGather
function, which only returns the comparison results but not does the filtering, and it gives the exact result as shown in the 2nd picture. But this lacks an automatic-filtering procedure and obviously it is not the complete version of hardware PCF.
Upvotes: 2
Views: 4118
Reputation: 97
By the answer of @Nicol, I think I misunderstood the meaning of interpolation. Following is my implementation of a shader-level interpolation, which looks exactly like the 2nd picture in the question:
Upvotes: 0
Reputation: 473926
To erase the blocky-effect, I've tried to do a 2x2 PCF manually in the shader. It leads to the following result, which also seems to be correct:
The OpenGL specification does not dictate the specific algorithm to be used when linearly interpolating depth comparisons. However, it generally describes it as:
The details of this are implementation-dependent, but
r
should be a value in the range [0,1] which is proportional to the number of comparison passes or failures.
That's not very constraining on, and it certainly does not require the output that you see as "correct".
Indeed, actual PCF differs quite a lot from what you are suggesting that you want. What you seem to want is still very blocky; it just not binary blocks. Your algorithm didn't linearly interpolate between the comparison results; you just did the 4 nearest comparisons and averaged them together.
What NVIDIA is giving you is what PCD is actually supposed to look like: linear interpolation between the comparison results, based on the point you're sampling from.
So it's your expectations that are wrong, not NVIDIA.
Upvotes: 3