I am trying to implement layered rendering to render cascaded shadow maps in one pass via geometry shader. The idea is to use GL_TEXTURE_2D_ARRAY with 3 texture for each cascade. This is the framebuffer init code:
CSMTarget::CSMTarget(int w, int h) : _width(w), _height(h){
// generate buffers:
glGenTextures(1, &_layeredTexture);
glGenFramebuffers(1, &_frameBuffer);
//glGenRenderbuffers(1, &_depthrenderbuffer);
// configure texture:
glBindTexture(GL_TEXTURE_2D_ARRAY, _layeredTexture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB32F, _width, _height, 3, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _layeredTexture, 0);
// depth render buffer:
//glBindRenderbuffer(GL_RENDERBUFFER, _depthrenderbuffer);
//glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, _width, _height);
//glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthrenderbuffer);
GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, DrawBuffers);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Frame buffer is complete.
Rendering to framebuffer:
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glViewport(0, 0, _width, _height);
//bind and update shader
//geometry pass
//unbind framebuffer
geometry shader:
#version 330
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec2 uv_vert0[];
out vec2 uv_frag0;
uniform mat4 viewProjMatrices[3];
void main() {
for(int face = 0; face < 3; face++) {
gl_Layer = face;
for(int i = 0; i < 3; i++) {
uv_frag0 = uv_vert0[i];
gl_Position = viewProjMatrices[face] * gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
}
Matrices are updated by glUniformMatrix4fv from array of 3 4x4 matrices.
And this is the part of directional light fragment shader that checks whether pixel is in shadow or not.
#version 330
vec2 sampleSM_A(inout float bias){
vec4 shadowUV = pc.dirLight.matrixA * vec4(data.worldPos,1);
shadowUV.xyz = shadowUV.xyz * 0.5 + 0.5;
if(shadowUV.x > 1 || shadowUV.y > 1 || shadowUV.x < 0 || shadowUV.y < 0) return vec2(-1.0, 0.0);
bias = 0.00025;
return vec2(texture(shadowMap, vec3(shadowUV.xy, 0)).x, shadowUV.z);
}
For sampleSM_B and C shadow map is sampled with texture(shadowMap, vec3(shadowUV.xy, LAYER_ID)). Red is first frustum split, green and pink are second and third.
The problem is that only first split works correctly. Shadow mapping works fine for all three splits when I use 3 frame buffers with texture_2D and 3 passes.
This is enabled glEnable(GL_TEXTURE_2D_ARRAY).
Is it a good idea if I use MRT with 3 textures instead of layered rendering?