【问题标题】:Render to texture problems渲染到纹理问题
【发布时间】:2012-01-04 21:16:20
【问题描述】:

我很想渲染到纹理工作,但遇到了一些麻烦。我正在尝试在屏幕上渲染一个简单的四边形,以确保一切正常。

    target->enable();

    glBegin(GL_QUADS);

    glColor4f(1.f, 0.f, 0.f, 1.f);
    glVertex3f(0.f, 0.f, 0.f);

    glColor4f(0.f, 1.f, 0.f, 1.f);
    glVertex3f(16.f, 0.f, 0.f);

    glColor4f(0.f, 0.f, 1.f, 1.f);
    glVertex3f(0.f, 16.f, 0.f);

    glColor4f(1.f, 1.f, 0.f, 1.f);
    glVertex3f(16.f, 16.f, 0.f);

    glEnd();

    target->disable();

当我正常地将四边形绘制到屏幕上时,四边形按预期呈现。但是,当我在启用渲染目标的情况下绘制四边形时,四边形会在屏幕的左下角渲染,最终不会渲染到目标。

RenderTarget::RenderTarget(GraphicsDevice *graphics, GLuint width, GLuint height) {

    mWidth = width;
    mHeight = height;

    // First create the depth buffer
    glGenRenderbuffers(1, &mDepth);
    glBindRenderbuffer(GL_RENDERBUFFER_EXT, mDepth);

    // Tell OpenGL that this renderbuffer is going to be a depth buffer
    glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, mWidth, mHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);

    glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);

    // Create the frame buffer texture
    glGenTextures(1, &mTexture);
    glBindTexture(GL_TEXTURE_2D, mTexture);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glBindTexture(GL_TEXTURE_2D, 0);

    // Create the frame buffer
    glGenFramebuffers(1, &mFbo);
    glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo);

    // Attach the texture
    glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, mTexture, 0);

    //Attach the depth buffer
    glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mFbo);

    glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);


}

RenderTarget::~RenderTarget() {
    glDeleteBuffers(1, &mFbo);
    glDeleteBuffers(1, &mDepth);
    glDeleteTextures(1, &mTexture);
    mFbo = 0;
    mDepth = 0;
    mTexture = 0;
}

void RenderTarget::enable() {
    // Bind the frame buffer
    glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo);
    // store the glViewport and glEnable states
    //glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);

    glClearColor(1.f, 0.f, 0.f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.f, 0.f, 0.f, 0.f);

    glLoadIdentity();
}

void RenderTarget::disable() {
    // Restore glViewport and glEnable states
    glPopAttrib();
    glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
}

【问题讨论】:

  • 您的 FBO 是 complete 吗?你似乎没有打电话给glCheckFramebufferStatus()
  • 是的,带着 GL_FRAMEBUFFER_COMPLETE_EXT 回来了。

标签: c++ opengl fbo


【解决方案1】:

您的启用是用glLoadIdentity 重置当前矩阵(很可能是模型视图)。这解释了为什么你的方块被移动到屏幕的角落。

您已注释掉对glPushAttrib 的调用,但没有注释掉对glPopAttrib 的匹配调用。如果您不在其他任何地方使用glPushAttrib,这应该设置一个错误标志并单独保留 GL 状态,但我不知道是这种情况,假设属性堆栈为空且始终为空是很麻烦的。

This 文档 glBindFrameBuffer 建议您应该使用 GL_FRAMEBUFFERGL_DRAW_FRAMEBUFFER 作为第一个参数:

target 必须是 GL_DRAW_FRAMEBUFFER、GL_READ_FRAMEBUFFER 或 GL_FRAMEBUFFER。如果帧缓冲区对象绑定到 GL_DRAW_FRAMEBUFFER 或 GL_READ_FRAMEBUFFER,它成为目标 分别呈现或回读操作,直到它被删除或 另一个帧缓冲区绑定到相应的绑定点。打电话 glBindFramebuffer 目标设置为 GL_FRAMEBUFFER 绑定 framebuffer 到读取和绘制帧缓冲区目标。

代码中带有 _EXT 后缀的枚举可能与此处记录的版本之前的 OpenGL 版本有关。教程很容易让这样的细节过时。

检查您的环境并依赖与您的 OpenGL 版本相匹配的文档。如果由于某种原因您无法轻松确定您的 OpenGL 版本,请在调用 glBindFrameBuffer 后检查 GL_INVALID_ENUM 错误。

【讨论】:

    【解决方案2】:

    此代码似乎错误:

    //Attach the depth buffer
    glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mFbo);
    

    您在这里所做的是尝试将 mFbo 作为渲染缓冲区附加到 mFbo。但是,您已经正确附加了渲染缓冲区(这是在第一次调用 glFramebufferRenderbuffer() 时完成的)。我认为删除该代码应该可以解决您的问题。

    【讨论】:

      【解决方案3】:

      正如我所怀疑的,我的问题是在渲染 FBO 时正确设置了 glViewport 和 glOrtho。这段代码需要清理,但这是我修复它的方法。

      void RenderTarget::enable() {
          // Bind the frame buffer
      
          glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo);
          // store the glViewport and glEnable states
          //glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
      
          glViewport(0, 0, mWidth, mHeight);
          // projection matrix
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
      
          // orthographic projection
          glOrtho(0, mWidth, 0, mHeight, -1, 1);
      
          glMatrixMode(GL_MODELVIEW);
          glLoadIdentity();
      
          glClearColor(1.f, 0.f, 0.f, 1.f);
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
          glClearColor(0.f, 0.f, 0.f, 0.f);
      
          glLoadIdentity();
      }
      
      void RenderTarget::disable() {
          // Restore glViewport and glEnable states
          //glPopAttrib();
          glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
          glViewport(0, 0, 1024, 768);
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
      
          // orthographic projection
          glOrtho(0, 1024, 768, 0, -1, 1);
      
          glMatrixMode(GL_MODELVIEW);
          glLoadIdentity();
      }
      

      【讨论】:

      • 在我上面发布的代码中,我手动将矩阵模式重置为正常设置。有没有办法通过推送/弹出到堆栈来做到这一点?我尝试了 glPushMatrix/glPopMatrix,但这似乎并没有像我预期的那样工作
      • glPushAttribGL_TRANSFORM_BIT 将保存矩阵模式以及其他一些状态。查看文档了解详细信息。
      猜你喜欢
      • 1970-01-01
      • 2018-03-18
      • 2010-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多