当前位置: 动力学知识库 > 问答 > 编程问答 >

opengl - Layered rendering to CUBEMAP using geometry shader

问题描述:

I am trying to render to all 6 faces of cubemap with a single drawcall.The GL cubemap is attached to an offscreen frame buffer object.The result I am getting is only the face number zero is affected by both frame buffer clear color and the fragment shader output.The goal is to use geometry shader which is invoked 6 times (once per face),then the gl_InstanceID is assigned to built-in gl_Layer.Fragment shader stage would read gl_Layer value and shade the raster based on in.It is expected that all 6 faced will be painted with a unique color that depends on gl_Layer value.

For the tests to see that I am getting correct gl_layer value I'm trying to render the layer id into the alpha channel of the texture by the following fragment shader:

#version 430

// Ouput data

layout(location = 0) out vec4 color;

in int gl_Layer;

void main(){

color = vec4(0.5,0.5,0.5,float(gl_Layer)/255.0);

}

The vertex shader basically do nothing:

#version 430

in vec3 position;

void main(){

gl_Position = vec4(position, 1.0);

}

and the geometry shader executes 6 times, render a unit square (covers the whole viewport) and sets gl_Layer according to gl_InvocationID:

#version 430

layout(triangles, invocations = 6) in;

layout(triangle_strip, max_vertices = 4) out;

out int gl_Layer;

void main()

{

const vec2 vert_data[4] = vec2[]( vec2(-1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, 1.0), vec2(1.0, -1.0) );

for(int i=0; i<4; i++)

{

gl_Layer = gl_InvocationID;

gl_Position = vec4(vert_data[i].xy,0,1);

EmitVertex();

}

EndPrimitive();

}

and finally, this is how I set the texture and the framebuffer:

 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &fbtextures_count);

// how many textures to create? depends on complexity of your effects.

glActiveTexture(GL_TEXTURE0);

glGenFramebuffers(1, &framebuffer);

glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

glGenTextures(1, &fbcubetexture);

GLenum target = GL_TEXTURE_CUBE_MAP;

// initializing color maps

glBindTexture(target, fbcubetexture);

glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

initData(255,255, 255);

for (int i = 0; i < 6; i++)

{

glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, cube_s, cube_s, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

}

glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fbcubetexture, 0);

GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };

glDrawBuffers(1, drawBuffers);

glReadBuffer(GL_COLOR_ATTACHMENT0);

glDrawBuffer(GL_COLOR_ATTACHMENT0);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

I am reading the faces colors on the client with:

 for (int i = 0; i < 6; i++)

{

glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA,GL_UNSIGNED_BYTE, data);

}

The result I get for GL_TEXTURE_CUBE_MAP_POSITIVE_X, is correct. but the rest of the face stay with the same first initialized value.I also debugged using NVIDIA NSIGHT where the whole cubemap texture is seen with only one face painted.

I read tens of examples which show how to use gl_Layer id for multi-target rendering through geometry shader but all of them do it differently.

For example,it is not clear if it is enough to attach cubemap texture to a single render target of FBO,or each face must be attached to a different render target?

Should glFramebufferTexture be used to bind the attachments or glFramebufferTexture2D ?

When cubemap is attached to the framebuffer is glClearColor supposed to clear all the faces to some color or just the first one?

What do I miss here?Anyone can show how to do it the right way?

System specs:

GPU:NVIDIA GeForce 960 GTX

Windows7 64bit

MSVC120

网友答案:

I can't prove this is the problem. But it is certainly one problem:

for(int i=0; i<4; i++)

You said that your GS takes triangles as inputs. Well, those only have three vertices, not 4. So your triangle strip will have a bad vertex in it.

When looping over items in a GS, it's always safer to do this:

for(int i = 0; i < gl_in.length(); i++)

That way, if you change the input primitive type, your length automatically gets updated.

分享给朋友:
您可能感兴趣的文章:
随机阅读: