C++ 将屏幕外帧缓冲区纹理渲染到主帧缓冲区

C++ 将屏幕外帧缓冲区纹理渲染到主帧缓冲区,c++,opengl,textures,framebuffer,C++,Opengl,Textures,Framebuffer,我正在尝试处理一个无法控制其设置方式的帧缓冲区对象。因此,我正在创建一个具有深度的屏幕外fbo来绘制我的纹理。然后将其绘制到主帧缓冲区。我现在可以使用OpenGL profiler从资源中看到纹理,但我似乎无法将其绘制到主帧缓冲区 这是我的密码 GLsizei glSizeWidthEquiv = width; GLsizei glSizeHeightEquiv = height; GLint originalFramebuffer; glGet

我正在尝试处理一个无法控制其设置方式的帧缓冲区对象。因此,我正在创建一个具有深度的屏幕外fbo来绘制我的纹理。然后将其绘制到主帧缓冲区。我现在可以使用OpenGL profiler从资源中看到纹理,但我似乎无法将其绘制到主帧缓冲区

这是我的密码

GLsizei glSizeWidthEquiv = width;
        GLsizei glSizeHeightEquiv = height;

        GLint originalFramebuffer;
        glGetIntegerv(GL_FRAMEBUFFER_BINDING, &originalFramebuffer);

        if(fbo == 0){
            glGenFramebuffers(1, &fbo);
        }
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);

        //Creating texture for framebuffer
        if(texColorBuffer == 0){
            glGenTextures(1, &texColorBuffer);
        }
        glBindTexture([outTex target], texColorBuffer);
        //Having it as null means the texture's data will be created dynamically
        //Using RGBA since the alpha layer is going to be needed
        glTexImage2D([outTex target], 0, GL_RGBA_FLOAT16_APPLE, glSizeWidthEquiv, glSizeHeightEquiv, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

        glTexParameteri([outTex target], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri([outTex target], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        //Attach texture to framebuffer
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, [outTex target], texColorBuffer, 0);

        //Creating render buffer
        if(renderBuffer == 0){
            glGenRenderbuffers(1, &renderBuffer);
        }
        glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, glSizeWidthEquiv, glSizeHeightEquiv);

        //Binding the renderbuffer to the framebuffer
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);

        //Check framebuffer
        if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
            NSLog(@"Framebuffer incomplete noob\n");
        }else{
            NSLog(@"Framebuffer COMPLETE!\n");
        }
        //Start to use the frame buffer
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        glViewport(0, 0, glSizeWidthEquiv, glSizeHeightEquiv);
        //cleaning texture: cleaning code here

        //initating glTex0
        glActiveTexture(GL_TEXTURE0);

        //setting up texture stuff
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                    glClearColor(0, 0, 0, 1);
        glDisable(GL_CULL_FACE);

        glColor3f(1,0,0);


        glBegin(GL_QUADS);
        //box 1 in front
        glVertex3f(0, 0, 0);
        glVertex3f(500, 0, 0);
        glVertex3f(500, 500, 0);
        glVertex3f(0, 500, 0);

        //box 2 at the back
        glColor3f(0, 1, 0);
        glVertex3f(-250, -250, 50);
        glVertex3f(250, -250, 50);
        glVertex3f(250, 250, 50);
        glVertex3f(-250, 250, 50);
        glEnd();

        glFogCoordf(9);
        //End of framebuffer usage
        glBindFramebuffer(GL_FRAMEBUFFER, originalFramebuffer);
        glViewport(0, 0, (GLsizei)[outTex width], (GLsizei)[outTex height]);
        [self glGetError];

        glActiveTexture(GL_TEXTURE0);
        glBindTexture([outTex target], texColorBuffer);
        glCopyTexSubImage2D([outTex target], 0, 0, 0, 0, 0, glSizeWidthEquiv, glSizeHeightEquiv);


        glFlush();
程序的这一部分位于渲染部分,我在初始化时将fbo、renderBuffer和texColorBuffer设置为0,以防止它生成新的缓冲区

所以本质上我创建缓冲区直到它完成,然后重新绑定我创建的fbo来绘制我的形状。切换回原始fbo并尝试绘制它

此处使用的[outTex目标]是GL_纹理_矩形_ARB

这是我在OpenGL Profiler的纹理部分中的内容:

@Gmasuchi

我不完全确定这是否是创建sscce的正确方法,但这里有一个易于复制粘贴的代码,包括库、GLUT和OpenGL。 这里使用的代码是从www.videotutorialsrock.com照明课程中提取的,因此我有一个类似的环境

#include <iostream>
#include <stdlib.h>

#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

using namespace std;

GLuint fbo,texColorBuffer,renderBuffer;
float  camMatrix [4][4];
//Initializes 3D rendering
void initRendering() {
    glEnable(GL_DEPTH_TEST);

}

//Called when the window is resized
void handleResize(int w, int h) {
    glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}

//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glTranslatef(0.0f, 0.0f, -8.0f);


if(fbo == 0){
    glGenFramebuffers(1, &fbo);
}
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

if(texColorBuffer == 0){
    glGenTextures(1, &texColorBuffer);
}
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 400, 400, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0);

if(renderBuffer == 0){
    glGenRenderbuffers(1, &renderBuffer);
}
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 400, 400);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
    printf("Error in framebuffer completeness \n");
}
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, 400, 400);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glActiveTexture(GL_TEXTURE0);

glBegin(GL_QUADS);
glColor3f(1,0,0);
glVertex3f(0, 0, 0);
glVertex3f(200, 0, 0);
glVertex3f(200, 200, 0);
glVertex3f(0, 200, 0);

glColor3f(0, 1, 0);
glVertex3f(-100, -100, -1);
glVertex3f(100, -100, -1);
glVertex3f(100, 100, -1);
glVertex3f(-100, 100, -1);

glEnd();

glFogCoordf(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, (GLsizei)400, (GLsizei)400);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 400, 400);

glutSwapBuffers();
}

void update(int value) {
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}

int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);

//set fbo,texBuffer and renderbuffer to 0
fbo = 0;
texColorBuffer = 0;
renderBuffer = 0;

//Create the window
glutCreateWindow("Lighting - videotutorialsrock.com");
initRendering();

//Set handler functions
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);

glutTimerFunc(25, update, 0); //Add a timer

glutMainLoop();
return 0;
}
#包括
#包括
#苹果__
#包括
#包括
#否则
#包括
#恩迪夫
使用名称空间std;
GLuint fbo、texColorBuffer、renderBuffer;
浮点数矩阵[4][4];
//初始化三维渲染
void initRendering(){
glEnable(GLU深度试验);
}
//调整窗口大小时调用
空心把手尺寸(内宽内高){
glViewport(0,0,w,h);
glMatrixMode(GL_投影);
glLoadIdentity();
(45.0,(双)w/(双)h,1.0200.0);
}
//绘制三维场景
void drawsecene(){
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
glMatrixMode(GLU模型视图);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-8.0f);
如果(fbo==0){
GLGEN帧缓冲区(1,&fbo);
}
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
如果(texColorBuffer==0){
glGenTextures(1,&texColorBuffer);
}
glBindTexture(GL_TEXTURE_2D,texColorBuffer);
GLTEXAGE2D(GL_纹理_2D,0,GL_RGBA,400,400,0,GL_RGBA,GL_无符号_字节,0);
glTexParameteri(GL_纹理2D、GL_纹理最小过滤器、GL_线性);
glTexParameteri(GL_纹理2D、GL_纹理MAG_过滤器、GL_线性);
glFramebufferTexture2D(GL_帧缓冲区,GL_颜色_附件0,GL_纹理_2D,texColorBuffer,0);
如果(renderBuffer==0){
glGenRenderbuffers(1,&renderBuffer);
}
glBindRenderbuffer(GL_RENDERBUFFER,RENDERBUFFER);
glRenderbufferStorage(GL_RENDERBUFFER,GL_depth 24_模具8、400、400);
glFramebufferRenderbuffer(GL_帧缓冲区、GL_深度、模具附件、GL_RENDERBUFFER、RENDERBUFFER);
如果(glCheckFramebufferStatus(GL\U FRAMEBUFFER)!=GL\U FRAMEBUFFER\U COMPLETE){
printf(“帧缓冲区完整性错误\n”);
}
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
glViewport(0,040400);
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
玻璃纹理(GL_纹理0);
glBegin(GL_QUADS);
gl3f(1,0,0);
glVertex3f(0,0,0);
glVertex3f(200,0,0);
glVertex3f(200200,0);
glVertex3f(0,200,0);
gl3f(0,1,0);
glVertex3f(-100,-100,-1);
glVertex3f(100,-100,-1);
glVertex3f(100100,-1);
glVertex3f(-100100,-1);
格伦德();
glFogCoordf(0);
glBindFramebuffer(GL_帧缓冲区,0);
glViewport(0,0,(GLsizei)400,(GLsizei)400);
玻璃纹理(GL_纹理0);
glBindTexture(GL_TEXTURE_2D,texColorBuffer);
glCopyTexSubImage2D(GL_纹理_2D,0,0,0,0,400,400);
glutSwapBuffers();
}
无效更新(int值){
再发现();
glutTimerFunc(25,更新,0);
}
int main(int argc,字符**argv){
//初始化过剩
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_双精度| GLUT_RGB | GLUT_深度);
glutInitWindowSize(400400);
//将fbo、texBuffer和renderbuffer设置为0
fbo=0;
texColorBuffer=0;
renderBuffer=0;
//创建窗口
glutCreateWindow(“Lighting-videotutorialsrock.com”);
initRendering();
//设置处理程序函数
glutDisplayFunc(绘图场景);
GLUTEFUNC(handleResize);
glutTimerFunc(25,更新,0);//添加计时器
glutMainLoop();
返回0;
}

以前从未使用过
glcopytextsubimage2d
,这是我对opengl手册页的最好解释

大宗报价 glCopyTexSubImage2D将二维纹理图像的矩形部分、立方体贴图纹理图像或一维阵列纹理的多个切片的线性部分替换为来自当前GL_读取_缓冲区(而不是来自主内存,如glTexSubImage2D)的像素

听起来好像您正在将
texColorBuffer
中的内容替换为
originalFramebuffer

我在屏幕上绘制帧缓冲区对象的方式是使用带纹理的全屏四边形,如下所示:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
glPushMatrix();
    GLfloat identity[4][4];
    for (int i=0; i<4; ++i){
        for (int j=0; j<4; ++j){
            identity[i][j] = 0;
        }
    }
    identity[0][0] = identity[1][1] = identity[2][2] = identity[3][3] = 1;
    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(identity);
    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(identity);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture([outTex target], texColorBuffer);

    glBegin(GL_QUADS);
        glVertex2f(-1,-1);
        glTexCoord2f(0, 0);

        glVertex2f( 1,-1);
        glTexCoord2f(1, 0);

        glVertex2f( 1, 1);
        glTexCoord2f(1, 1);

        glVertex2f(-1, 1);
        glTexCoord2f(0, 1);
    glEnd();
glPopMatrix();
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
glClearColor(0,0,0,1);
glPushMatrix();
GLfloat标识[4][4];

对于(int i=0;i您很有可能会发布一篇文章,帮助我们了解我们可以如何提供帮助?就目前而言,从您上面的内容来看,我们可能会尽最大努力避免出现与您上面的代码不符的错误。干杯:)我尝试从fbo绑定纹理并绘制一个类似于您的示例的四边形,但最终只得到我在伪SSCCE中包含的一个正方形的颜色。另外,在其中,我创建了两个不同z坐标的正方形来区分其距离,我想渲染它,包括它的z坐标。是的,只有绿色的一个我通过使用glBlitframebuffer使它工作,显然我添加了我不需要的额外帧缓冲区,它一直在屏幕外渲染。