Using sampler2DShadow with multisampled deferred rendering breaks

500 views Asked by At

As the title states, using a sampler2DShadow causes an error in the lighting shader of my multisampling FBO, but I cannot detect the problem due to having a very similar configuration using a standard deferred rendering setup without multisampling, which works fine.

Is there a compatibility issue with sampler2DShadow and multisampling in openlGL, or some alternative I should be using?

The shaders compile fine.

The code works fine until I run this line:

texture(gShadowMap2D, vec3(pCoord.xy, (pCoord.z) / pCoord.w));

and retrieve the result. I then get GL_INVALID_OPERATION.

The shadow map is from a directional light (depth map is valid and visible) and uses GL_COMPARE_R_TO_TEXTURE, set to a standard texture (GL_TEXTURE_2D).

The multisampling deferred FBO textures uses GL_TEXTURE_2D_MULTISAMPLE.

I'm using glsl 330 (openGL 3.3 core profile).

UPDATE

I think the problem is related to getting the world position from the position map in the multisampled fragment shader.

The standard way:

vec3 worldPos = texture(gPositionMap, texCoord).xyz;

The multisampled way:

vec2 texCoordMS = floor(vertTextureSize * texCoord.xy);

for(int i = 0; i < samples; i++)
{
    worldPos += texelFetch(gPositionMapMS, ivec2(texCoordMS), i).xyz;
}

worldPos = worldPos / samples;

(I omitted the other samplers.)

I'm guessing I am out of bounds which throws the error when trying to access the sampler2DShadow (pCoord is calculated using worldPos).

Now to figure out how to get this multisampled worldPos to get the same result as the standard way???

Standard way (mDepthVP = mat4 (light's depth view prog):

vec4 coord = gLight.mDepthVP * vec4(worldPos, 1.0);
1

There are 1 answers

0
Rebirth On

Well, after almost pulling my hair out desperately searching for a single hint as to why this problem was happening I finally figured it out, but I'm not entirely sure why it was causing the problem.

During the geometry pass (before the lighting pass) the models are rendered to the position, colour (diffuse), normals and depth-stencil as you would expect. During this pass a texture in binded (the diffuse texture of a mesh) but only as a standard texture (GL_TEXTURE_2D) at unit zero (GL_TEXTURE0) (I'm only using diffuse for now).

I left it like that as the system worked, because the lighting pass overrides that unit when it binds the four FBO textures for reading. However, in the multisampling FBO they were being binded as multisampling textures (GL_TEXTURE_2D_MULTISAMPLE) and it just happens that the 'position' map was using unit zero (GL_TEXTURE0).

For some reason this didn't overwrite the previously bound unit from the geometry pass and caused the GL_INVALID_OPERATION error. After calling:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0); 

straight after the geometry pass the problem went away.

The question I ask comes down to asking "why didn't it overwrite?"