将缓冲区内容返回到OpenGL中的纹理

时间:2012-02-14 18:48:02

标签: c++ opengl

为了让我的迷宫式游戏更快,我决定将我的绘制球放在纹理中,因为我必须为每个房间绘制一次,我使用模板缓冲区将其绘制成凹形多边形,需要更多时间比使用纹理。问题是,当我从游戏开始渲染第三帧时,我正在从后缓冲区正确地将它放入纹理中,我的问题是,为什么会这样?

当我使用来自口渴框架的纹理时,我的纹理具有纯白色,因此内部没有任何东西。当我使用第二帧的纹理时,我只有所需纹理的黑色背景,当我从第三帧中获取纹理时,我就有了所需的纹理。对于帧计数,我在“drawTexture”函数中使用静态变量“done”。

从第一帧复制:

enter image description here

从第二帧复制:

enter image description here

从第三帧复制(期望的结果):

enter image description here

void DrawBall::drawTexture(float imageD) {
    static int done = 0;

    if (done < 3) {
        drawToTexture(imageD);
        done++;
    }

    glEnable(GL_TEXTURE_2D);
    glBindTexture (GL_TEXTURE_2D, texture);

    glColor3f(1, 1, 1);
    glBegin (GL_QUADS);
        glTexCoord2f (0.0, 0.0); glVertex3f (0.0, 0.0, -imageD);    
        glTexCoord2f (1.0, 0.0); glVertex3f (5.0, 0.0, -imageD);
        glTexCoord2f (1.0, 1.0); glVertex3f (5.0, 5.0, -imageD);    
        glTexCoord2f (0.0, 1.0); glVertex3f (0.0, 5.0, -imageD);
    glEnd ();

    glDisable(GL_TEXTURE_2D);   
}

void DrawBall::drawToTexture(float imageD) {
    int viewport[4];
    glGetIntegerv(GL_VIEWPORT, (int*) viewport);

    int textureWidth = 64;
    int textureHeight = 64;

    texture = genEmptyTexture(textureWidth, textureHeight);

    glViewport(0, 0, textureWidth, textureHeight);
    glMatrixMode(GL_PROJECTION);                            
    glLoadIdentity();                                       
    gluPerspective(45.0f, 1, 1, 100);
    glMatrixMode(GL_MODELVIEW);                         
    glLoadIdentity();                                       

    /* 
       This function calculates the vertexes for the ball
       inside a vector<vector<float>> variable "test"
    */
    _calculateCircleVertexes(0.0f, 0.0f, -2.0f, 0.249f, &test, 20);

    _displayBall(&test, 0.0f, 0.0f, 0.5f, -2.0f, &*smallBallColor);

    glBindTexture(GL_TEXTURE_2D, texture);
    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, textureWidth, textureHeight, 0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
    glMatrixMode(GL_PROJECTION);    
    glLoadIdentity();               
    gluPerspective(45.0f, (GLfloat)viewport[2] / (GLfloat)viewport[3], 1.0f, imageD + 10.0f);
    glMatrixMode(GL_MODELVIEW);     
    glLoadIdentity();   
}

GLuint DrawBall::genEmptyTexture(unsigned int width, unsigned int height) {
    GLuint txtIndex;

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

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
    GL_RGB, GL_UNSIGNED_BYTE, NULL);                            

    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);

    return txtIndex;
}

void DrawBall::_displayBall(vector<vector<GLfloat>> *vertexes, GLfloat x, GLfloat y
                        , GLfloat imageW, GLfloat imageD, color *color) {
    glTranslatef(x, y, imageD);

    glClearStencil(0);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_NEVER, 0, 1);
    glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);

    glBegin(GL_POLYGON);
        vector<vector<GLfloat>>::iterator it = vertexes->begin();
        for (; it != vertexes->end(); it++) {
            glVertex3f((*it)[0], (*it)[1], 0.0f);
        }
    glEnd();

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glStencilFunc(GL_EQUAL, 1, 1);
    glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);

    glColor3f(color->r, color->g, color->b);
    glBegin(GL_QUADS);
        glVertex3f(-(imageW / 2.0f), -(imageW / 2.0f), 0.0f);
        glVertex3f( (imageW / 2.0f), -(imageW / 2.0f), 0.0f);
        glVertex3f( (imageW / 2.0f),  (imageW / 2.0f), 0.0f);
        glVertex3f(-(imageW / 2.0f),  (imageW / 2.0f), 0.0f);
    glEnd();

    glDisable(GL_STENCIL_TEST);

    glTranslatef(x, y, -imageD);
}

2 个答案:

答案 0 :(得分:2)

您不应该使用窗口帧缓冲区(包括后缓冲区和前缓冲区)来渲染纹理操作。它只是容易打破(你已经体验过)。而是使用所谓的 Framebuffer Object ,将纹理作为渲染目标。

答案 1 :(得分:0)

嗯,Datenwolf,谢谢你的建议,你可能是对的,但我只想尽可能少地使用高级的东西,我发现了我的错误。在第二帧之前我没有得到理想的结果,因为我还没有启用模板测试。在第一帧之前我没有得到所需的结果,因为在窗口创建中Windows发送了WM_SIZE消息,我在其中有了绘制消息,但那时OpenGL还没有正确设置。