OpenGL: Rendering to texture by using FBO and viewport offset problems

三世轮回 提交于 2019-12-10 00:44:11

问题


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

We get same results:

But, if we change first line to:

glViewport(x, y, w, h);

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

Why green and red drawing do not match?


回答1:


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.




回答2:


If width() == w and height() == h (the w & h values in your resize function), then your texture (and FBO) size is different from your viewport size. To be explicit, your viewport is (w-100) * (h-100) and your texture is (w-150) * (h-150).



来源:https://stackoverflow.com/questions/22072578/opengl-rendering-to-texture-by-using-fbo-and-viewport-offset-problems

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!