2010-11-24 81 views
15

我想渲染一个场景到最初为空的纹理。为此,我使用了一个Framebuffer对象,我在其上附加了一个空的2d纹理和深度缓冲区。设置完成后,就测试而言,我在场景中绘制了一个简单的四边形。每个顶点都有不同的颜色,所以我最终期望在纹理中使用颜色插值的四边形。 然后我使用包含四边形的纹理并将其映射到另一个四边形上。因此,在我的默认Framebuffer中有一个四边形,它具有包含彩色四边形的纹理。我希望这不是太混乱...OpenGL:渲染到纹理和帧缓冲区对象时遇到问题

无论如何,我必须在这里失去一些东西,因为我得到的只是灰色的纹理。我基本上遵循this指令,这些指令非常简单。但是,我无法弄清楚我在这里失去了什么。如果有人能给我提供线索,我将不胜感激。

由于 沃尔特


这是代码我迄今为止: //创建帧缓冲器对象 glGenFramebuffers(1,& frameBufferObject);

// create depth buffer 
glGenRenderbuffers(1, &depthAttachment); 

// create empty texture 
int width = 512; 
int height = 512; 
int numberOfChannels = 3; 
GLuint internalFormat = GL_RGB; 
GLuint format = GL_RGB; 

unsigned char* texels = new unsigned char[width * height * numberOfChannels]; 

glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_2D, texture); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, texels); 

glGenerateMipmap(GL_TEXTURE_2D); 

delete[] texels; 
texels = NULL; 

// activate & bind empty texture 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, texture); 

// attach empty texture to framebuffer object 
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 

// define render targets (empty texture is at GL_COLOR_ATTACHMENT0) 
glDrawBuffers(1, GL_COLOR_ATTACHMENT0); 

// attach depth buffer 
glBindRenderbuffer(GL_RENDERBUFFER, depthAttachment); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthAttachment); 

// use framebuffer object 
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject); 

// draw the colored quad into the initially empty texture 
glDisable(GL_CULL_FACE); 
glDisable(GL_DEPTH_TEST); 

// store attibutes 
glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

// reset viewport 
glViewport(0, 0, width, height); 

// make background yellow 
glClearColor(1.0f, 1.0f, 0.0f, 1.0f); 

// draw quad into texture attached to frame buffer object 
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 
glBegin(GL_QUADS); 
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glVertex2f(0.0f, 100.0f); // top left 
    glColor4f(1.0f, 0.0f, 0.0f, 1.0f); glVertex2f(0.0f, 0.0f); // bottom left 
    glColor4f(0.0f, 1.0f, 0.0f, 1.0f); glVertex2f(100.0f, 0.0f); // bottom right 
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f); glVertex2f(100.0f, 100.0f); // top right 
glEnd(); 

// restore attributes 
glPopAttrib(); 

glEnable(GL_DEPTH_TEST); 
glEnable(GL_CULL_FACE); 

// use default framebuffer 
glBindFramebuffer(GL_FRAMEBUFFER, 0); 

// clear default framebuffer 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

// draw the scene 
glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
glLoadIdentity(); 

glColor4f(1.0, 1.0, 1.0, 1.0); 

// begin texture mapping 
glEnable(GL_TEXTURE_2D); 
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 

glBegin(GL_QUADS); 
    glNormal3d(0.0f, 0.0f, 1.0f); 
    glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 50.0f, -100.0f); // top left 
    glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, 0.0f, -100.0f);  // bottom left 
    glTexCoord2f(1.0f, 1.0f); glVertex3f(50.0f, 0.0f, -100.0f); // bottom right 
    glTexCoord2f(1.0f, 0.0f); glVertex3f(50.0f, 50.0f, -100.0f); // top right 
glEnd(); 

glDisable(GL_TEXTURE_2D); 

glPopMatrix(); 

// swap buffers (I forgot to mention that I use SDL) 
SDL_GL_SwapBuffers(); 

预期结果:

  • 质地与在黄色背景上的彩色四
  • 即纹理上的另一个四元映射

实际结果:

  • 灰色纹理
  • 纹理可以成功地在另一四映射

编辑:我错过提错误处理。这是我如何检查错误。它包括Paul S建议的其他案例。感谢那。

GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 
switch(status) { 
    case GL_FRAMEBUFFER_COMPLETE: 
     return; 
     break; 

case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 
    throw FramebufferIncompleteException("An attachment could not be bound to frame buffer object!"); 
    break; 

case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 
    throw FramebufferIncompleteException("Attachments are missing! At least one image (texture) must be bound to the frame buffer object!"); 
    break; 

case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: 
    throw FramebufferIncompleteException("The dimensions of the buffers attached to the currently used frame buffer object do not match!"); 
    break; 

case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: 
    throw FramebufferIncompleteException("The formats of the currently used frame buffer object are not supported or do not fit together!"); 
    break; 

case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: 
    throw FramebufferIncompleteException("A Draw buffer is incomplete or undefinied. All draw buffers must specify attachment points that have images attached."); 
    break; 

case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: 
    throw FramebufferIncompleteException("A Read buffer is incomplete or undefinied. All read buffers must specify attachment points that have images attached."); 
    break; 

case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: 
    throw FramebufferIncompleteException("All images must have the same number of multisample samples."); 
    break; 

case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS : 
    throw FramebufferIncompleteException("If a layered image is attached to one attachment, then all attachments must be layered attachments. The attached layers do not have to have the same number of layers, nor do the layers have to come from the same kind of texture."); 
    break; 

case GL_FRAMEBUFFER_UNSUPPORTED: 
    throw FramebufferIncompleteException("Attempt to use an unsupported format combinaton!"); 
    break; 

default: 
    throw FramebufferIncompleteException("Unknown error while attempting to create frame buffer object!"); 
    break; 
} 

编辑2:这是我用它来检查GL-错误的方法

checkForGLErrors(string sourceFile, int line) 
    GLenum error = glGetError(); 
    ostringstream o; 

    switch(error) { 
     case GL_NO_ERROR: 
      return; 
      break; 

     case GL_INVALID_ENUM: 
      o<<"OpenGL Error in "<<sourceFile<<" at line "<<line<<": Invalid enum!"<<endl; 
      throw GLErrorException(o.str()); 
      break; 

     case GL_INVALID_VALUE: 
      o<<"OpenGL Error in "<<sourceFile<<" at line "<<line<<": Invalid value!"<<endl; 
      throw GLErrorException(o.str()); 
      break; 

     case GL_INVALID_OPERATION: 
      o<<"OpenGL Error in "<<sourceFile<<" at line "<<line<<": Invalid operation!"<<endl; 
      throw GLErrorException(o.str()); 
      break; 

     case GL_STACK_OVERFLOW: 
      o<<"OpenGL Error in "<<sourceFile<<" at line "<<line<<": Stack overflow!"<<endl; 
      throw GLErrorException(o.str()); 
      break; 

     case GL_STACK_UNDERFLOW: 
      o<<"OpenGL Error in "<<sourceFile<<" at line "<<line<<": Stack underflow!"<<endl; 
      throw GLErrorException(o.str()); 
      break; 

     case GL_OUT_OF_MEMORY: 
      o<<"OpenGL Error in "<<sourceFile<<" at line "<<line<<": Out Of memory!"<<endl; 
      throw GLErrorException(o.str()); 
      break; 

     case GL_TABLE_TOO_LARGE: 
      o<<"OpenGL Error in "<<sourceFile<<" at line "<<line<<": Table too large!"<<endl; 
      throw GLErrorException(o.str()); 
      break; 

     default: 
      o<<"OpenGL Error in "<<sourceFile<<" at line "<<line<<": Unknown error!"<<endl; 
      throw GLErrorException(o.str()); 
      break; 
    } 
} 
+0

你使用哪种版本的OpenGL? framebuffer对象函数没有任何供应商后缀,所以我倾向于相信3.0 - 3.3,但我很怀疑。请记住,OpenGL 3核心功能GL_ARB_framebuffer_object和GL_EXT_framebuffer_object存在主要差异。他们不一样!此外,仅调用glCheckFramebufferStatus()是不够的。确保你处理正常的OpenGL错误以及glGetError() – 2010-11-25 05:11:23

+0

你的假设是正确的。我正在使用OpenGL 3.1。我应该早一点提及。 感谢glGetError()提示。我将它包含在我的代码中。我将该方法添加到上面的代码清单中。我想我会检查可能由OpenGL 3.1发起的所有错误,不是吗?我检查了整个代码中的错误,但似乎没有任何内容。 – Walter 2010-11-25 06:54:38

+2

我越来越怀疑它不是包含错误的应用程序,但可能会分别丢失或错误地设置一些库或扩展。我不确定这是否有任何帮助,但这是我的系统:Windows 7,OpenGL 3.1,NVidia Quadro FX 3700.我正在使用GLEW 1.5.7,SDL 1.2,GL_EXT_framebuffer_object,GL_EXT_texture3D,GL_ARB_draw_buffers ...任何想法是赞赏。 – Walter 2010-11-26 02:01:57

回答

1

我希望发生的事情之一:

  • 你从空置的MIP渲染地图级别。在渲染彩色四边形之前,您已经调用了glGenerateMipmap。现在就试试GL_NEAREST。
  • 创建帧缓冲区对象时出现错误。如果发生这种情况,你的渲染将会落在一个黑洞中。

这是我用来检查帧缓冲区状态的一段代码。它使用EXT版本的FBO,并且在Objective-C(因此是@“”字符串)中,但它应该很明显。它在我调用glBindFramebuffer之后,glFramebufferTexture2D & glDrawBuffers。

GLenum framebufferStatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 

    switch (framebufferStatus) { 
     case GL_FRAMEBUFFER_COMPLETE_EXT: break; 
     case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: 
      NSLog(@"Framebuffer Object %d Error: Attachment Point Unconnected", i); 
      break; 
     case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: 
      NSLog(@"Framebuffer Object %d Error: Missing Attachment", i); 
      break; 
     case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: 
      NSLog(@"Framebuffer Object %d Error: Dimensions do not match", i); 
      break; 
     case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: 
      NSLog(@"Framebuffer Object %d Error: Formats", i); 
      break; 
     case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: 
      NSLog(@"Framebuffer Object %d Error: Draw Buffer", i); 
      break; 
     case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: 
      NSLog(@"Framebuffer Object %d Error: Read Buffer", i); 
      break; 
     case GL_FRAMEBUFFER_UNSUPPORTED_EXT: 
      NSLog(@"Framebuffer Object %d Error: Unsupported Framebuffer Configuration", i); 
      break; 
     default: 
      NSLog(@"Framebuffer Object %d Error: Unkown Framebuffer Object Failure", i); 
      break; 
    } 

的问题很可能是深度缓冲,因为司机往往是相当挑剔这一点。对于这个测试你不需要深度,所以你可以删除渲染缓冲区的东西,如果它导致问题。

另一个需要注意的是,纹理不需要被绑定和激活来渲染它。你可以推迟这段代码,直到你想用它来渲染你的最终图像。

+0

对不起,我错过了上述代码中的错误处理。我确实检查了framebuffer状态。不过,我认为我不检查每一个可能的错误。我忘了检查GL_FRAMEBUFFER_INCOMPLETE_DIMENSION_EXT和GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT,这当然是非常重要的。我加了这两个例子。不幸的是,这既没有改变,也没有返回错误信息。我已将错误检查添加到上述代码中。 – Walter 2010-11-25 01:04:30

4

奇怪的是,两个glDrawBuffersglFramebufferTexture2D看起来不像规格!第一个需要GLENUM的数组,而不是GLenum(检查警告:它可以默默铸造!)。而第二个只有4个参数的规格!

编辑:

void glDrawBuffers(GLsizei n, const GLenum * bufs); 
5

我解决了这个问题。

所以这就是我所做的。也许有一些更好/更聪明的方法来做到这一点,但现在它工作得很好。随意建议适配...

我没有列出下面的错误处理。你可以在这个问题中进一步找到。


// create frame buffer object 
glGenFramebuffers(1, frameBufferObject); 

// create empty texture 
int width = 512; 
int height = 512; 
int numberOfChannels = 3; 
GLuint internalFormat = GL_RGB8; 
GLuint format = GL_RGB; 

unsigned char* texels = new unsigned char[width * height * numberOfChannels]; 

glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_2D, texture); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, texels); 

delete[] texels; 
texels = NULL; 

// draw the colored quad into the initially empty texture 
glDisable(GL_CULL_FACE); 
glDisable(GL_DEPTH_TEST); 

// store attibutes 
glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

// reset viewport 
glViewport(0, 0, width, height); 

// setup modelview matrix 
glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
glLoadIdentity(); 

// setup projection matrix 
glMatrixMode(GL_PROJECTION); 
glPushMatrix(); 
glLoadIdentity(); 

// setup orthogonal projection 
glOrtho(-width/2, width/2, -height/2, height/2, 0, 1000); 

// bind framebuffer object 
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject); 

// attach empty texture to framebuffer object 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 

// check framebuffer status (see above) 

// bind framebuffer object (IMPORTANT! bind before adding color attachments!) 
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject); 

// define render targets (empty texture is at GL_COLOR_ATTACHMENT0) 
glDrawBuffers(1, GL_COLOR_ATTACHMENT0); // you can of course have more than only 1 attachment 

// activate & bind empty texture 
// I figured activating and binding must take place AFTER attaching texture as color attachment 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, texture); 

// clear color attachments 
glClear(GL_COLOR_BUFFER_BIT); 

// make background yellow 
glClearColor(1.0f, 1.0f, 0.0f, 1.0f); 

// draw quad into texture attached to frame buffer object 
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 
glBegin(GL_QUADS); 
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glVertex2f(0.0f, 100.0f); // top left 
    glColor4f(1.0f, 0.0f, 0.0f, 1.0f); glVertex2f(0.0f, 0.0f); // bottom left 
    glColor4f(0.0f, 1.0f, 0.0f, 1.0f); glVertex2f(100.0f, 0.0f); // bottom right 
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f); glVertex2f(100.0f, 100.0f); // top right 
glEnd(); 

// reset projection matrix 
glMatrixMode(GL_PROJECTION); 
glPopMatrix(); 

// reset modelview matrix 
glMatrixMode(GL_MODELVIEW); 
glPopMatrix(); 

// restore attributes 
glPopAttrib(); 

glEnable(GL_DEPTH_TEST); 
glEnable(GL_CULL_FACE); 

// I guess, now it's OK to create MipMaps 

// draw the scene 
glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
glLoadIdentity(); 

glColor4f(1.0, 1.0, 1.0, 1.0); 

// begin texture mapping 
glEnable(GL_TEXTURE_2D); 
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 

    // normal faces "camera" 
    glNormal3d(0.0f, 0.0f, 1.0f); 

    glBegin(GL_QUADS); 
     glNormal3d(0.0f, 0.0f, 1.0f); 
     glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 50.0f, -100.0f); // top left 
     glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, 0.0f, -100.0f);  // bottom left 
     glTexCoord2f(1.0f, 1.0f); glVertex3f(50.0f, 0.0f, -100.0f); // bottom right 
     glTexCoord2f(1.0f, 0.0f); glVertex3f(50.0f, 50.0f, -100.0f); // top right 
    glEnd(); 

glDisable(GL_TEXTURE_2D); 

glPopMatrix(); 

// finish rendering 
glFlush(); 
glFinish(); 

// swap buffers (I forgot to mention that I use SDL) 
SDL_GL_SwapBuffers(); 

// do the clean up! 

正如你看到的,我摆脱了深度缓冲附件。我觉得我并不需要它来完成我的任务。只要我真的可以画东西,我就添加了正交投影。不这样做,绘图纹理的结果很尴尬的图片...

希望这是对别人有用那里 沃尔特

相关问题