简体   繁体   中英

Cube map render texture creation works in GL 3.2 but gives an error in 4.3

I'm using the following code to create a cube map render target:

glGenTextures( 1, &id );
glBindTexture( GL_TEXTURE_CUBE_MAP, id );

glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );

// Creates a renderbuffer object to store depth info.
GLuint bufferId;
glGenRenderbuffers( 1, &bufferId );

glBindRenderbuffer( GL_RENDERBUFFER, bufferId );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height );
glBindRenderbuffer( GL_RENDERBUFFER, 0 );

glGenFramebuffers( 1, &fboId );
glBindFramebuffer( GL_FRAMEBUFFER, fboId );

const GLenum externalFormat = GL_RGBA;
const GLenum internalFormat = GL_RGBA8;
const GLenum dataType = GL_UNSIGNED_BYTE;

for (int i = 0; i < 6; ++i)
{
    glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internalFormat,
                 size, size, 0, externalFormat,
                 dataType, nullptr );
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, id, 0 );
}

glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, bufferId );

It doesn't generate any OpenGL errors in OpenGL 3.2 context but when running the same code under OpenGL 4.3 context, debug output callback gives the following error on glFramebufferTexture2D:

OpenGL: Framebuffer unsupported. Attachment COLOR_ATTACHMENT0 unsupported because it uses an inconsistent texture due to invalid texture parameters.

I'm running the code on Windows 8.1 with NVIDIA GeForce GT 750M, driver 337.88. Am I creating the render target wrongly?

I'm not sure what the error is about, but maybe related to a mismatch between size , width and height .

Regardless, there's a few other issues:

  1. Each loop iteration simply overrides GL_COLOR_ATTACHMENT0 . Perhaps change to GL_COLOR_ATTACHMENT0 + i .

  2. However this means you must write to every layer in the cube when ever a fragment passes the depth test.

  3. You also have a single renderbuffer with just one layer which means a single depth test is used for all sides of your cube.

I don't think the above is what you want anyway.

  • To render to a cube texture you could bind each layer in turn, rendering the whole scene multiple times each from a new projection. This is the old way of doing it.

    Example

  • To render to a cube texture with just one rendering pass you can bind the entire cube map (which is really just 6 layers of a regular texture) to GL_COLOR_ATTACHMENT0 . For depth testing, you create and bind another cube texture (or renderbuffer, but not sure if you can) with GL_DEPTH_COMPONENT to GL_DEPTH_ATTACHMENT . Then in the geometry shader you duplicate everything 6 times, one for each face of your cube. gl_Layer in the geometry shader is used to set which face in the cube the primitive draws to. Come to think of it you could also use instancing ( glDrawElementsInstanced / gl_InstanceID ) to duplicate your geometry 6 times which would shift computation from the geometry shader to the vertex shader and may be a little faster if your vertex operations are expensive.

    Example

In both cases you'll need a 90 degree projection matrix with aspect ration 1 and will need to rotate the view to match the cube faces (this is pretty fiddly so save your code for future use). So create 6 the view matrices and pass them in to either the geometry or vertex shader depending on whether you use instancing or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM