使用FBO和视口偏移问题渲染到纹理

使用FBO和视口偏移问题渲染到纹理

本文介绍了OpenGL:使用FBO和视口偏移问题渲染到纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到渲染到纹理时帧缓冲对象(FBO)的意外行为.

I have noticed unexpected behavior of frame-buffer objects (FBO) when rendering to a texture.

如果我们通过以下方式设置视口:

If we set viewport in following way:

glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;

(w和h不需要匹配窗口大小)一切都呈现得很好:

(w and h doesn't need to match window size) everything is rendered fine:

所以可以说我们需要绘制视口的边界矩形:

So lets say we need to draw bounding rectangle of viewport:

glBegin(GL_LINE_STRIP);
    glVertex2f(0.0, 0.0);
    glVertex2f(0.0, 1.0);
    glVertex2f(1.0, 1.0);
    glVertex2f(1.0, 0.0);
glEnd();

如果我们在纹理上进行相同的绘制,然后覆盖整个视口:

If we do the same drawing on a texture then covering whole viewport:

glBegin(GL_QUADS);
    glTexCoord2f(0.0, 1.0);
    glVertex2f(0.0, 0.0);
    glTexCoord2f(0.0, 0.0);
    glVertex2f(0.0, 1.0);
    glTexCoord2f(1.0, 0.0);
    glVertex2f(1.0, 1.0);
    glTexCoord2f(1.0, 1.0);
    glVertex2f(1.0, 0.0);
glEnd();

我们得到相同的结果:

但是,如果我们将第一行更改为:

But, if we change first line to:

glViewport(x, y, w, h);

其中x和y不等于0-执行FBO版本时会有一个奇怪的偏移量.偏移量完全等于(x,y),但它相对于视口,因此我们得到的偏移量为(2 * x,2 * y)

where x and y are NOT equal 0 - there is a strange offset when doing FBO version. Offset is exactly equal to (x, y) but it is relative to a viewport so we get resulting offset off (2*x, 2*y)

这里是完整的代码,演示了问题.

Here is full code demonstrating problem.

void initialize()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
}

void resize(int w, int h)
{
    glViewport(50, 50, w-100, h-100);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluOrtho2D(0.0, 1.0, 1.0, 0.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity() ;
}

void paint()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // FBO Drawing
    GLuint fb, texColor;
    glGenFramebuffers(1, &fb);
    glGenTextures(1, &texColor);

    glBindFramebuffer(GL_FRAMEBUFFER, fb);
    glBindTexture(GL_TEXTURE_2D, texColor);
    glTexImage2D(   GL_TEXTURE_2D,
                0,
                GL_RGBA,
                width()-100, height()-100, // Maching size of viewport (size of window - unused area)
                0,
                GL_RGBA,
                GL_UNSIGNED_BYTE,
                NULL);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0);

    glLineWidth(10.0);
    glColor4f(1.0, 0.0, 0.0, 1.0);
    glBegin(GL_LINE_STRIP);
        glVertex2f(0.0, 0.0);
        glVertex2f(0.0, 1.0);
        glVertex2f(1.0, 1.0);
        glVertex2f(1.0, 0.0);
    glEnd();
    glBegin(GL_LINES);
        glVertex2f(0.0, 0.0);
        glVertex2f(1.0, 1.0);
        glVertex2f(0.0, 1.0);
        glVertex2f(1.0, 0.0);
    glEnd();


    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    glLineWidth(10.0);
    glColor4f(0.0, 1.0, 0.0, 1.0);
    glBegin(GL_LINE_STRIP);
        glVertex2f(0.0, 0.0);
        glVertex2f(0.0, 1.0);
        glVertex2f(1.0, 1.0);
        glVertex2f(1.0, 0.0);
    glEnd();
    glBegin(GL_LINES);
        glVertex2f(0.0, 0.0);
        glVertex2f(1.0, 1.0);
        glVertex2f(0.0, 1.0);
        glVertex2f(1.0, 0.0);
    glEnd();

    glEnable(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, texColor);
    glColor4f(1.0, 1.0, 1.0, 0.3);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0, 1.0);
        glVertex2f(0.0, 0.0);
        glTexCoord2f(0.0, 0.0);
        glVertex2f(0.0, 1.0);
        glTexCoord2f(1.0, 0.0);
        glVertex2f(1.0, 1.0);
        glTexCoord2f(1.0, 1.0);
        glVertex2f(1.0, 0.0);
    glEnd();

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    glDeleteTextures(1, &texColor);
    glDeleteFramebuffers(1, &fb);

为什么绿色和红色图形不匹配?

推荐答案

您当然会获得两倍的视口-因为您基本上将其两次应用了-视口在渲染纹理时也很有效,所以最终得到对象原点映射到纹理中的像素(x,y).然后,再次使用视口绘制该纹理,以便四边形从窗口坐标的(x,y)开始,并且纹理中的对象进一步移开-两个偏移量累积.

You of course get the twice the viewport - since you basically apply it twice - the viewport is also effective when rendring to the texture, so you end up with the object origin mappted to pixel (x,y) in the texture. Then, you draw that texture, again with the viewport, so the quad begins at (x,y) in window coords, and the object in the texture is further shifted away - the two offsets accumulate.

只需将视口设置为在渲染到纹理中时从原点开始.

Just set the viewport to begin at origin when you render into the texture.

这篇关于OpenGL:使用FBO和视口偏移问题渲染到纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 12:56