PDA

View Full Version : How to initialize an array cube map



Harukoxd
11-05-2016, 05:10 PM
I don't understand how exactly initialize a cube map array, i tried it with the next code which didn't throw me an error, but i don't know if it is correct. Even if it works, i prefer to know if it looks great for you because i didn't find that much information about array cube maps on internet.

Then, i want an array cube map for point light shadow mapping (also i'll use cube maps arrays for reflections, but it is simpler then i decided to start with it). The code that i used to initialize it is the following:




// Generate frame buffer
glGenFramebuffers(1, &m_fbo);

// Generate a render buffer for the depth buff
glGenRenderbuffers(1, &m_depthBuffer);

// Set up the render buffer for depth
glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, WindowWidth, WindowHeight);

// Set it to the frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);

// Generate the cube map array texture
glGenTextures(1, &m_CubeShadowMap);

// Set up the cube map array texture
glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_CubeShadowMap);

// I dont want bipmap for this cube map because it is a shadow map. I want it to be RG because ill use VSM later, which require two channels
glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RG32F, WindowWidth, WindowHeight, numCubeMaps);
for (int i = 0; i < numCubeMaps; i++)
{
for (int face = 0; face < 6; face++)
{
// Creating all the faces
glTexSubImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, 0, 0, i, WindowWidth, WindowHeight, 0, GL_RG, GL_UNSIGNED_BYTE, NULL);
}
}

// Setting parameters
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);


// Checking status
GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

if (Status != GL_FRAMEBUFFER_COMPLETE)
{
printf("FB error, status: 0x%x\n", Status);
return false;
}
// Change to default framebuffer before finishing
glBindFramebuffer(GL_FRAMEBUFFER, 0);

return true;


I want to know if it looks great for you, specially the faces creation, which is the part that i have not idea if it is correct.

Also i am not sure if the following is the way to bind a cube's face to the framebuffer:



void CubeShadowMapFBO::BindForWriting(int Face, int cube)
{
assert(Face < 6);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + Face, m_CubeShadowMap,0,cube);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}


Thank you very much for your attention, i know that it is a lot of questions about it, but i didn't find really extend information about it on internet :(

GClements
11-05-2016, 07:29 PM
glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RG32F, WindowWidth, WindowHeight, numCubeMaps);


For a cube map array, width and height must be equal, and depth must be a multiple of six (i.e. it's the total number of layer-faces, which is six times the number of cube maps in the array).





glTexSubImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, 0, 0, i, WindowWidth, WindowHeight, 0, GL_RG, GL_UNSIGNED_BYTE, NULL);


This isn't valid. To specify texture data for a cube map array, you need to use GL_TEXTURE_CUBE_MAP_ARRAY. The zoffset and depth values are in layer-faces, i.e. values of 0 through 5 refer to the faces of the first cube map in the array, 6 through 11 faces of the second cube map, and so on.



Also i am not sure if the following is the way to bind a cube's face to the framebuffer:

Use glFramebufferTexture() to attach all layer-faces, resulting in a layered framebuffer, or glFramebufferTextureLayer() to attach a specific layer-face.

Harukoxd
11-05-2016, 08:21 PM
For a cube map array, width and height must be equal, and depth must be a multiple of six (i.e. it's the total number of layer-faces, which is six times the number of cube maps in the array).


This isn't valid. To specify texture data for a cube map array, you need to use GL_TEXTURE_CUBE_MAP_ARRAY. The zoffset and depth values are in layer-faces, i.e. values of 0 through 5 refer to the faces of the first cube map in the array, 6 through 11 faces of the second cube map, and so on.


Use glFramebufferTexture() to attach all layer-faces, resulting in a layered framebuffer, or glFramebufferTextureLayer() to attach a specific layer-face.

Thank you very much for answer. I have changed what you said, it looks like this now:



glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_CubeShadowMap);
glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RG32F, CubeSize, CubeSize, numCubeMaps*6);
glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, CubeSize, CubeSize, numCubeMaps * 6, GL_RG, GL_UNSIGNED_BYTE, NULL);


And for binding a face to the FBO:



void CubeShadowMapFBO::BindForWriting(int Face, int cube)
{
assert(Face < 6);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_CubeShadowMap, 0, (cube*6) + Face);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}


Is it ok now? I think that i got the idea, but it is just to check if i understood it correctly.