OpenGL ES FBO Scaling

旧城冷巷雨未停 提交于 2019-12-08 04:34:27

问题


This question is a follow up to the original question as recommended by Matic Oblak

Once an FBO is setup and rendered to, how is the rendered image provided back to the default render buffer and displayed in a scaled version.

-(void)setupFBO {
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
}

Rendering to the FBO first:

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport (0, 0, 160, 144);
glClearColor (1.0f, 0.0f, 0.0f, 0.5f);
glClear (GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glViewport(0, 0, 160, 144);

glBindVertexArrayOES(_vertexArray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

If i uncomment the fbo binding, the square is displayed correctly - so i don't think its an issue with the VBO and VAO.

Attempt to display the result back to the main view scaled up to fit screen:

[((GLKView *) self.view) bindDrawable];
glViewport (0, 0, view.frame.size.width, view.frame.size.height);
glClearColor (0.0f, 1.0f, 0.0f, 0.5f);
glClear (GL_COLOR_BUFFER_BIT);

//vb2 has the scaled vertex coordinates
glBindBuffer(GL_ARRAY_BUFFER, vb2);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);

//make sure we are not redrawing the same thing? the texture should be
//a colored cube based on what the fbo rendered.
glDisableVertexAttribArray(GLKVertexAttribColor);

//create a buffer for the texture coordinates
//should be moved in setup phase, but left in for testing
glGenBuffers(1, &texBuffer);
glBindBuffer(GL_ARRAY_BUFFER, texBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*8, squareTex, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0, 0);
//bind to the fbo texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

Some of the tutorials I've read and followed.

  1. OpenGL FBO Example
  2. Songho OGL FBO
  3. RTT

Ultimately, i want an emulated GB screen of (160x144 pixels) to be displayed in the full width of the simulator (maintaining height ratio).

Im starting with a small square and trying to stretch it out to achieve the retro squared pixel effect.


回答1:


To achieve a stretched effect all you need to do is draw a full screen rectangle with the texture. If no matrices are used you simply need to set vertex position data in range [-1,1] so for triangle strip:

{-1, -1,
  1, -1,
 -1,  1,
  1,  1}

The texture coordinates should be dependent on the original texture viewport ratio to texture size. For your example of 160x144 the nearest large enough texture size data would be 256x256 which results in ratio = (160/256, 144/256) so the coordinates are

{.0,       .0,
ratio.x,   .0,
.0,        ratio.y,
ratio.x,   ratio.y}

If this does not show a result you will need to find an issue which may be at any point. To begin with I would first try to draw this coordinates with a solid color to see if the rectangle is drawn full screen. If it is then the issue is most likely in the texture received from the FBO. If I may assume you are working with Xcode the best tool is to create a frame snapshot (a tool found on the bottom left part) which will show you all the calls and all the textures at any point of the frame. With it you may see if the texture is correctly draw to.

Do not forget to check for openGL errors (glGetError) and to check the status of the FBO buffer after attachments glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE.

This is a method from one of my projects which creates a FBO. It might be of some use to you.

    glGenFramebuffers(1, &_frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);

    glGenRenderbuffers(1, &_renderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);

    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, texture.textureWidth, texture.textureHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffer);

    [texture bind];
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.textureID, 0);

    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_bufferWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_bufferHeight);

    [GLGlobalTools checkFramebufferStatus];
    [GLGlobalTools checkError];

    _bufferWidthf = _bufferWidth;
    _bufferHeightf = _bufferHeight;

    _surfaceWidth = (GLint)texture.imageWidth;
    _surfaceHeight = (GLint)texture.imageHeight;


来源:https://stackoverflow.com/questions/38071480/opengl-es-fbo-scaling

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