Масштабирование текстуры с помощью Framebuffer - PullRequest
2 голосов
/ 09 февраля 2011

Моя цель - иметь возможность масштабировать текстуры, когда они загружены, поэтому мне не нужно делать это для каждого кадра, который визуализирует спрайт. Я подумал, что лучшим способом было бы отрисовать масштабированную текстуру на другую текстуру, в основном кешируя ее. Однако с помощью следующего кода я получаю только красные квадраты (из-за glClearColor), поэтому я знаю, что FBO работает, но не мой метод рендеринга новой текстуры

Texture *Graphics::loadTexture(const std::string& filename, int scale = 0) {
SDL_Surface *surface;
GLuint texture;

if((surface = IMG_Load(filename.c_str()))) {
    // Get the number of colors
    GLint numberOfColors = surface->format->BytesPerPixel;
    GLenum format;

    // Set the format of the texture based on the number of channels
    if(numberOfColors == 4) {
            if(surface->format->Rmask == 0x000000ff) {
                format = GL_RGBA;
            } else {
                format = GL_BGRA;
            }
    } else if(numberOfColors == 3) {
        if(surface->format->Rmask == 0x000000FF) {
            format = GL_RGB;
        } else {
            format = GL_BGR;
        }
    } else {
        throw Exception("Invalid image type for image  " + filename); 
    }

    // Generate texture id
    glGenTextures(1, &texture);

    // Bind the texture
    glBindTexture(GL_TEXTURE_2D, texture);

    // Texture stretching properties
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    // Create the image
    glTexImage2D(GL_TEXTURE_2D, 0, 4, surface->w, surface->h, 
                0, format, GL_UNSIGNED_BYTE, surface->pixels);

    glBindTexture(GL_TEXTURE_2D, 0);

} else {
    return NULL;
}
Texture *result;

if(scale > 1) {
    GLuint scaledTexture;
    GLuint fbo;
    GLuint fbod;

    // First we setup the depth buffer //
    // Create the framebuffer
    glGenRenderbuffersEXT(1, &fbod);

    // Bind the render buffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbod);

    // Set the render buffer storage to be a depth component
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, surface->w*scale, surface->h*scale);

    // Set the render buffer of this buffer to the depth buffer
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbod);

    // Unbind the render buffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

    // Next we setup the texture //
    glGenTextures(1, &scaledTexture);
    glBindTexture(GL_TEXTURE_2D, scaledTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->w*scale, surface->h*scale, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glBindTexture(GL_TEXTURE_2D, 0);

    // Setup the frame buffer //
    glGenFramebuffersEXT(1, &fbo);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

    // Attach the texture and render buffer to the frame buffer
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  scaledTexture, 0);

    // Attach the depth buffer
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbod);

    glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
    glViewport(0, 0, surface->w*scale, surface->h*scale);

    glLoadIdentity();

    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindTexture(GL_TEXTURE_2D, texture);

    glPushMatrix();

    glBegin(GL_QUADS);
        glTexCoord2i( 0, 0 );
        glVertex3f( 0.f, 0.f, 0.0f );

        glTexCoord2i( 1, 0 );
        glVertex3f( (GLfloat)surface->w*scale, 0.0f, 0.0f );

        glTexCoord2i( 1, 1 );
        glVertex3f( (GLfloat)surface->w*scale, (GLfloat)surface->h*scale, 0.f );

        glTexCoord2i( 0, 1 );
        glVertex3f( 0.0f, (GLfloat)surface->h*scale, 0.f );
    glEnd();

    glPopMatrix();


    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glPopAttrib();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

    result = new Texture(scaledTexture, surface->w, surface->h);
} else {
    result = new Texture(texture, surface->w, surface->h);
}

//Texture *result = new Texture(texture, surface->w, surface->h);

if(surface) {
    SDL_FreeSurface(surface);
}

return result;
}

Ответы [ 3 ]

1 голос
/ 09 февраля 2011

Хорошо, я решил вместо масштабирования во время загрузки текстуры внедрить его в объект спрайта. Поэтому, когда я отправляю данные вершин в графический процессор, он масштабирует спрайт по вершинам вместо масштабирования фактической текстуры.

1 голос
/ 10 февраля 2011

Если не пытаться сказать вам, что делать, а вместо этого сказать вам самый простой способ сделать то, что вы хотите сделать (масштабировать текстуру) - ответ:

glBlitFramebuffer(sx0,sy0,sx1,sy1,dx0,dy0,dx1,dy1, GL_COLOR_BUFFER_BIT, GL_LINEAR)

Он автоматически масштабирует прочитанное изображение, если размер не совпадает Для того, чтобы это работало, вы должны настроить GL_READ_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER и glDrawBuffer () для каждого из них.

1 голос
/ 09 февраля 2011

Несколько комментариев:

  • Когда вы выполняете свой glLoadIdentity (), знаете ли вы, какую матрицу вы сбрасываете?Используйте glMatrixMode.
  • Ваш glPushMatrix () / glPopMatrix () бесполезен, поскольку вы не изменяете матрицу между ними.
  • Вы уверены, что 2D-текстуры включены?Используйте glEnable (GL_TEXTURE_2D);

Но в любом случае очистите обе матрицы, и вы должны увидеть свою текстуру в верхней правой части экрана (или любой другой многоугольник, на котором вы используете сгенерированную текстуру);вам просто нужно исправить UVs et Graphics :: loadTexture:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

Это должно сработать, но я думаю, что вы должны выполнить масштабирование в программном обеспечении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...