PDA

View Full Version : Texture 2D array as render target



markp
07-21-2010, 11:15 AM
Greetings OpenGL gurus,

I have been trying to use texture 2d arrays as render targets, but only the first layer turns out correct. Attached are some code snippits from a test application I created to work out the problem, I could not figure out how to attach the entire program as a zip file.

What I was expecting is to see a red triangle in the first layer, and a green one in the second layer. The red triangle appears correct, but the second layer is empty, as if it is being cleared but the triangle is not being drawn.

Does anyone have experience using these are render targets and can point out where I went wrong?


void CreateRenderTarget()
{
glGenTextures(1, &g_RenderTarget.color_texture);
glBindTexture(GL_TEXTURE_2D_ARRAY, g_RenderTarget.color_texture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, g_Width, g_Height, 2, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);

glGenTextures(1, &g_RenderTarget.depth_stencil_texture);
glBindTexture(GL_TEXTURE_2D_ARRAY, g_RenderTarget.depth_stencil_texture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, g_Width, g_Height, 2, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);

glGenFramebuffers(1, &g_RenderTarget.rt);
glBindFramebuffer(GL_FRAMEBUFFER, g_RenderTarget.rt);

glBindTexture(GL_TEXTURE_2D_ARRAY, g_RenderTarget.color_texture);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, g_RenderTarget.color_texture, 0);

glBindTexture(GL_TEXTURE_2D_ARRAY, g_RenderTarget.depth_stencil_texture);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, g_RenderTarget.depth_stencil_texture, 0);

GLenum fbok = glCheckFramebufferStatus(GL_FRAMEBUFFER);
_ASSERT(fbok == GL_FRAMEBUFFER_COMPLETE);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

_ASSERT(glGetError() == GL_NO_ERROR);
}


void DoFrame()
{
GLint old_draw_buffer;
glGetIntegerv(GL_DRAW_BUFFER, &old_draw_buffer);

glDisable(GL_BLEND);
glClearDepth(1.0f);
glFrontFace(GL_CCW);
glDisable(GL_CULL_FACE);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);

// Draw to render target.
glBindFramebuffer(GL_FRAMEBUFFER, g_RenderTarget.rt);
GLenum draw_buffer = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, &draw_buffer);
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glViewport(0, 0, g_Width, g_Height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

glBindVertexArray(g_DrawToTextureGeometry.vao);
glUseProgram(g_DrawToTextureShader.program);
glDrawArrays(GL_TRIANGLES, 0, 3);

// Draw contents of render target onto screen.
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer((GLenum)old_draw_buffer);
glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
glViewport(0, 0, g_Width, g_Height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

glBindVertexArray(g_DrawToScreenGeometry.vao);
glUseProgram(g_DrawToScreenShader.program);
glBindTexture(GL_TEXTURE_2D_ARRAY, g_RenderTarget.color_texture);
glUniform1i(g_DrawToScreenShader.input_texture_han dle, 0);
glUniform1f(g_DrawToScreenShader.which_layer_handl e, (float)g_WhichLayer);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
glBindVertexArray(0);

SwapBuffers(g_DC);

_ASSERT(glGetError() == GL_NO_ERROR);
}



#version 150

layout(triangles) in;
layout(triangle_strip, max_vertices = 6) out;

out float flag_gs2ps;

void main()
{
// First layer
gl_Position = gl_in[0].gl_Position;
flag_gs2ps = 0.0;
gl_Layer = 0;
EmitVertex();

gl_Position = gl_in[1].gl_Position;
flag_gs2ps = 0.0;
gl_Layer = 0;
EmitVertex();

gl_Position = gl_in[2].gl_Position;
flag_gs2ps = 0.0;
gl_Layer = 0;
EmitVertex();
EndPrimitive();

// Second layer
gl_Position = gl_in[0].gl_Position;
flag_gs2ps = 1.0;
gl_Layer = 1;
EmitVertex();

gl_Position = gl_in[1].gl_Position;
flag_gs2ps = 1.0;
gl_Layer = 1;
EmitVertex();

gl_Position = gl_in[2].gl_Position;
flag_gs2ps = 1.0;
gl_Layer = 1;
EmitVertex();
EndPrimitive();
}





#version 150

in float flag_gs2ps;

out vec4 color_psout;

void main()
{
if (flag_gs2ps < 0.5)
color_psout.rgb = vec3(1.0, 0.2, 0.2);
else if (flag_gs2ps < 1.5)
color_psout.rgb = vec3(0.2, 1.0, 0.2);
else
color_psout.rgb = vec3(0.2, 0.2, 1.0);

color_psout.a = 1.0;
}



Thank you for the assistance.

markp
07-22-2010, 04:34 PM
Actually, I think this is correct. It works as expected with the Nvidia 258.19 drivers, but is broken in the ATI 10.6 drivers.