opengl - framebuffer texture clipped smaller than I set it?

谁说我不能喝 提交于 2020-01-15 03:40:12

问题


I'm using opengl ES 2.0 I'm using a framebuffer linked to a texture to compile an offscreen render (of some simplistic metaballs), and then I'm rendering that texture to the main back buffer.

Everything is looking great except that the texture appears clipped, ie. it is not the full window dimensions (short of about 128 pixels on one axis). Here's a screenshot: http://tinypic.com/r/9telwg/7

Any ideas what could cause this? I read here to set glViewport to the size of the texture, but that gives me a different aspect ratio since the texture metaballsTexture is square (1024x1024) and my window is 768x1024. It also still remains a bit clipped, as it seems I can't get the frame buffer to be big enough, even though the texture is bigger than my window size. Below is my code. I call PrepareToAddMetaballs() during the render when I'm ready, then successive calls to AddMetaball, now rendered onto my offscreeen FBO, then FinishedAddingMetaballs when I'm done, and later call Render() to display the offscreen texture linked to the FBO onto the main backbuffer.

#include "Metaballs.h"
#include "s3e.h"
#include "IwGL.h"
#include "Render.h"
#include "vsml.h"
#include <vector>
#include <string>
#include <iostream>
#include "1013Maths.h"

#define GL_RGBA8 0x8058

MetaBalls::MetaBalls() : metaballsTexture(NULL), metaballsShader(NULL) {
    glGenFramebuffers(1, &myFBO);

    metaballTexture[0] = NULL;
    metaballTexture[1] = NULL;
    metaballTexture[2] = NULL;
    CRender::Instance()->CreateTexture("WaterCanvas.png", &metaballsTexture);
    CRender::Instance()->CreateTexture("metaball.pvr", &metaballTexture[0]);
    CRender::Instance()->CreateTexture("metaball-1.png", &metaballTexture[1]);
    CRender::Instance()->CreateTexture("metaball-2.png", &metaballTexture[2]);
    CRender::Instance()->CreateShader("Shaders/metaballs.fs", "Shaders/metaballs.vs", &metaballsShader);

    glBindFramebuffer(GL_FRAMEBUFFER, myFBO);
    // Attach texture to frame buffer
    glBindTexture(GL_TEXTURE_2D, metaballsTexture->m_id);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, metaballsTexture->m_id, 0);
    glClearColor(1,1,1,0);
    glClear(GL_COLOR_BUFFER_BIT);

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        std::string error = "Metaballs framebuffer incomplete";
        std::cerr << error << std::endl;
        throw error;
    }

    float w = PTM_DOWNSCALE(float(metaballsTexture->GetWidth()));
    float h = PTM_DOWNSCALE(float(metaballsTexture->GetHeight()));

    CRender::Instance()->BuildQuad(
        tVertex( b2Vec3(0,0,0), b2Vec2(0,1) ),
        tVertex( b2Vec3(w,0,0), b2Vec2(1,1) ),
        tVertex( b2Vec3(w,h,0), b2Vec2(1,0) ),
        tVertex( b2Vec3(0,h,0), b2Vec2(0,0) ),
        buffer);

}

MetaBalls::~MetaBalls() {
    CRender::Instance()->ReleaseShader(metaballsShader);
    CRender::Instance()->ReleaseTexture(metaballsTexture);
    CRender::Instance()->ReleaseTexture(metaballTexture[0]);
    CRender::Instance()->ReleaseTexture(metaballTexture[1]);
    CRender::Instance()->ReleaseTexture(metaballTexture[2]);
    glDeleteFramebuffers(1, &myFBO);
}

void MetaBalls::PrepareToAddMetaballs(b2Vec3& paintColour) {

    // bind render to texture
    glBindFramebuffer(GL_FRAMEBUFFER, myFBO);
    // Set our viewport so our texture isn't clipped (appears stretched and clipped)
    // glViewport(0, 0, metaballsTexture->GetWidth(), metaballsTexture->GetHeight());
    glClearColor(paintColour.x, paintColour.y, paintColour.z, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

}

void MetaBalls::FinishedAddingMetaballs() {
    glBindFramebuffer(GL_FRAMEBUFFER, NULL);
    // CRender::Instance()->SetWindowViewport();
}

void MetaBalls::AddMetaball(float x, float y, uint size) {

    // render the metaball texture to larger texture
    VSML::setIdentityMatrix(pTransform);
    pTransform[12] = PTM_DOWNSCALE(x);
    pTransform[13] = PTM_DOWNSCALE(y+4); // the +4 is for a bit of overlap with land
    float oldview[16];
    float identity[16];
    VSML::setIdentityMatrix(identity);
    memcpy(oldview, CRender::Instance()->GetViewMatrix(), sizeof(float)*16);
    memcpy(CRender::Instance()->GetViewMatrix(),identity, sizeof(float)*16);
    CRender::Instance()->DrawSprite(metaballTexture[size], pTransform, 1.0f, true);
    memcpy(CRender::Instance()->GetViewMatrix(),oldview, sizeof(float)*16);
}

void MetaBalls::Render() {

    VSML::setIdentityMatrix(pTransform);
    pTransform[12] = PTM_DOWNSCALE(-128);
    pTransform[13] = PTM_DOWNSCALE(-256);

    // render our metaballs texture using alpha test shader
    CRender::Instance()->BindShader(metaballsShader);
    CRender::Instance()->BindTexture(0, metaballsTexture);

    CRender::Instance()->SetMatrix(metaballsShader, "view", CRender::Instance()->GetViewMatrix());
    CRender::Instance()->SetMatrix(metaballsShader, "world", pTransform);
    CRender::Instance()->SetMatrix(metaballsShader, "proj", CRender::Instance()->GetProjMatrix());

    CRender::Instance()->SetBlending(true);
    CRender::Instance()->DrawPrimitives(buffer);
    CRender::Instance()->SetBlending(false);

}

====================

EDIT

Aha! Got it. I haven't found this example anywhere, but I fixed it by adjusting the perspective matrix. It was set to 1024x768 when it was working, but with a window size of 768x1024, the projection matrix was changing, as well as the viewport. By setting each to 1024x768 manually (I chose to use constants), the metaballs are rendered correctly offscreen with proper aspect ratio. Their 1024x1024 texture is rendered as a billboard with that aspect ratio nice and sharp. After I'm done I restore them to what the rest of the application uses. Below is the working code:

#include "Metaballs.h"
#include "s3e.h"
#include "IwGL.h"
#include "Render.h"
#include "vsml.h"
#include <vector>
#include <string>
#include <iostream>
#include "1013Maths.h"

MetaBalls::MetaBalls() : metaballsTexture(NULL), metaballsShader(NULL) {

    glGenFramebuffers(1, &myFBO);

    metaballTexture[0] = NULL;
    metaballTexture[1] = NULL;
    metaballTexture[2] = NULL;
    CRender::Instance()->CreateTexture("WaterCanvas.png", &metaballsTexture);
    CRender::Instance()->CreateTexture("metaball.pvr", &metaballTexture[0]);
    CRender::Instance()->CreateTexture("metaball-1.png", &metaballTexture[1]);
    CRender::Instance()->CreateTexture("metaball-2.png", &metaballTexture[2]);
    CRender::Instance()->CreateShader("Shaders/metaballs.fs", "Shaders/metaballs.vs", &metaballsShader);

    glBindFramebuffer(GL_FRAMEBUFFER, myFBO);

    // Attach texture to frame buffer
    glBindTexture(GL_TEXTURE_2D, metaballsTexture->m_id);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, metaballsTexture->m_id, 0);

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        std::string error = "Metaballs framebuffer incomplete";
        std::cerr << error << std::endl;
        throw error;
    }

    float w = PTM_DOWNSCALE(float(metaballsTexture->m_width));
    float h = PTM_DOWNSCALE(float(metaballsTexture->m_height));

    CRender::Instance()->BuildQuad(
        tVertex( b2Vec3(0,0,0), b2Vec2(0,1) ),
        tVertex( b2Vec3(w,0,0), b2Vec2(1,1) ),
        tVertex( b2Vec3(w,h,0), b2Vec2(1,0) ),
        tVertex( b2Vec3(0,h,0), b2Vec2(0,0) ),
        buffer);

    // return to default state
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

MetaBalls::~MetaBalls() {
    CRender::Instance()->ReleaseShader(metaballsShader);
    CRender::Instance()->ReleaseTexture(metaballsTexture);
    CRender::Instance()->ReleaseTexture(metaballTexture[0]);
    CRender::Instance()->ReleaseTexture(metaballTexture[1]);
    CRender::Instance()->ReleaseTexture(metaballTexture[2]);
    glDeleteFramebuffers(1, &myFBO);
}

void MetaBalls::PrepareToAddMetaballs(b2Vec3& paintColour) {

    // bind render to texture
    glBindFramebuffer(GL_FRAMEBUFFER, myFBO);

    // Set orthographic projection
    cfloat w = SCREEN_WIDTH / PTM_RATIO;
    cfloat h = SCREEN_HEIGHT / PTM_RATIO;
    VSML::ortho(-w, 0, -h, 0, 0.0f, -1.0f, CRender::Instance()->m_Proj);

    // Set our viewport so our texture isn't clipped
    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    glClearColor(paintColour.x, paintColour.y, paintColour.z, 0.1f);
    glClear(GL_COLOR_BUFFER_BIT);

}

void MetaBalls::FinishedAddingMetaballs() {
    glBindFramebuffer(GL_FRAMEBUFFER, NULL);
    CRender::Instance()->SetWindowViewport();
}

void MetaBalls::AddMetaball(float x, float y, uint size) {

    // render the metaball texture to larger texture
    VSML::setIdentityMatrix(pTransform);
    pTransform[12] = PTM_DOWNSCALE(x);
    pTransform[13] = PTM_DOWNSCALE(y);
    float oldview[16];
    float identity[16];
    VSML::setIdentityMatrix(identity);
    memcpy(oldview, CRender::Instance()->GetViewMatrix(), sizeof(float)*16);
    memcpy(CRender::Instance()->GetViewMatrix(),identity, sizeof(float)*16);
    CRender::Instance()->DrawSprite(metaballTexture[size], pTransform, 1.0f, true);
    memcpy(CRender::Instance()->GetViewMatrix(),oldview, sizeof(float)*16);
}

void MetaBalls::Render() {

    VSML::setIdentityMatrix(pTransform);
    pTransform[12] = PTM_DOWNSCALE(0);
    pTransform[13] = PTM_DOWNSCALE(-256);

    // render our metaballs texture using alpha test shader
    CRender::Instance()->BindShader(metaballsShader);
    CRender::Instance()->BindTexture(0, metaballsTexture);

    CRender::Instance()->SetMatrix(metaballsShader, "view", CRender::Instance()->GetViewMatrix());
    CRender::Instance()->SetMatrix(metaballsShader, "world", pTransform);
    CRender::Instance()->SetMatrix(metaballsShader, "proj", CRender::Instance()->GetProjMatrix());

    CRender::Instance()->SetBlending(true);
    CRender::Instance()->DrawPrimitives(buffer);
    CRender::Instance()->SetBlending(false);

}

回答1:


Are you setting your viewport according to the texture's size? I didnt find any view port setting on your code...



来源:https://stackoverflow.com/questions/7748730/opengl-framebuffer-texture-clipped-smaller-than-i-set-it

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