opengl - текстура фреймбуфера обрезана меньше, чем я установил?

Я использую opengl ES 2.0. Я использую фреймбуфер, связанный с текстурой, для компиляции закадрового рендеринга (некоторых упрощенных метабаллов), а затем рендеринг этой текстуры в основной задний буфер.

Все выглядит отлично, за исключением того, что текстура кажется обрезанной, т.е. это не полные размеры окна (не более 128 пикселей по одной оси). Вот скриншот: http://tinypic.com/r/9telwg/7

Есть идеи, что могло вызвать это? Я прочитал , чтобы установить glViewport на размер текстуры, но это дает мне другое соотношение сторон, так как текстура MetaballsTexture квадратная (1024x1024), а мое окно - 768x1024. Он также все еще остается немного обрезанным, поскольку кажется, что я не могу получить достаточно большой буфер кадра, даже если текстура больше, чем размер моего окна. Ниже мой код. Я вызываю PrepareToAddMetaballs () во время рендеринга, когда я готов, затем последовательные вызовы AddMetaball, теперь визуализируемые на моем внешнем FBO, затем FinishedAddingMetaballs, когда я закончу, и позже вызываю Render () для отображения закадровой текстуры, связанной с FBO. на основной буфер.

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

}

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

РЕДАКТИРОВАТЬ

Ага! Понятно. Я нигде не нашел этот пример, но исправил его, настроив матрицу перспективы. Когда он работал, он был установлен на 1024x768, но с размером окна 768x1024 менялась матрица проекции, а также область просмотра. Если вручную установить для каждого из них 1024x768 (я решил использовать константы), метабалы правильно отображаются за пределами экрана с правильным соотношением сторон. Их текстура 1024x1024 визуализируется как рекламный щит с красивым и четким соотношением сторон. После того, как я закончу, я восстанавливаю их до того, что использует остальная часть приложения. Ниже рабочий код:

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

}

person Ryan    schedule 13.10.2011    source источник
comment
Мне удалось сделать все это видимым в разрешении 1024x768, установив для преобразования x и y значение 0 при рендеринге, но если я установил окно с размером 768x1024, его нижняя часть обрезается (по-моему, на 256 пикселей). Я думаю, это потому, что я все еще рисую его в горизонтальной ориентации, но я поворачиваю матрицу вида на 90 градусов (когда ipad вращается). Так кажется, что часть, отрисованная за кадром, обрезается? Это из-за окна просмотра?   -  person Ryan    schedule 13.10.2011


Ответы (1)


Вы настраиваете область просмотра в соответствии с размером текстуры? Я не нашел настройки порта просмотра в вашем коде ...

person André Puel    schedule 13.10.2011
comment
привет, да, вы можете видеть, что я пробовал это в функции PrepareToAddMetaballs, в настоящее время она закомментирована, хотя она только слегка растягивала текстуру в ширину, но проблема с отсечением остается. - person Ryan; 13.10.2011
comment
Вы установили свою перспективную матрицу? - person André Puel; 13.10.2011
comment
Я только что нашел сообщение с той же проблемой, но без решения, это может помочь прояснить ситуацию. stackoverflow.com/questions/5041098/ - person Ryan; 13.10.2011
comment
Также потребовалась настройка матрицы перспективы, см. Выше. Для тех, кто читает, также обратите внимание, когда он работал, казалось, что у него плохое разрешение, поэтому необходимо было настроить допуск в моем шейдере метаболизма. Не совсем уверен, почему это так, но после того, как я его настроил, он добился четкого попиксельного сглаживания. - person Ryan; 13.10.2011
comment
Я потратил 1 час, чтобы понять, что не так с постобработкой изображения из-за той же проблемы. - person bruziuz; 05.10.2020