渲染大纹理到较小的Renderbuffer

时间:2012-09-14 22:09:07

标签: ios opengl-es

我有一个852x640的渲染缓冲区和一个1280x720的纹理。当我渲染纹理时,它会被裁剪,而不仅仅是拉伸。我知道宽高比需要校正,但我怎样才能获得它以便在渲染缓冲区中显示完整的纹理?

//-------------------------------------
    glGenFramebuffers(1, &frameBufferHandle);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferHandle);

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

    [oglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];

    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &renderBufferWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &renderBufferHeight);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBufferHandle);
//-------------------------------------


static const GLfloat squareVertices[] = {
    -1.0f, 1.0f,
    1.0f, 1.0f,
    -1.0f,  -1.0f,
    1.0f,  -1.0f
};

static const GLfloat horizontalFlipTextureCoordinates[] = {
    0.0f, 1.0f,
    1.0f, 1.0f,
    0.0f,  0.0f,
    1.0f,  0.0f,
};

size_t frameWidth = CVPixelBufferGetWidth(pixelBuffer);
size_t frameHeight = CVPixelBufferGetHeight(pixelBuffer);

CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, 
                                                            videoTextureCache,
                                                            pixelBuffer,
                                                            NULL,
                                                            GL_TEXTURE_2D,
                                                            GL_RGBA,
                                                            frameWidth,
                                                            frameHeight,
                                                            GL_BGRA,
                                                            GL_UNSIGNED_BYTE,
                                                            0,
                                                            &texture);


if (!texture || err) {
    NSLog(@"CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err);  
    return;
}

glBindTexture(CVOpenGLESTextureGetTarget(texture), CVOpenGLESTextureGetName(texture));

glViewport(0, 0, renderBufferWidth, renderBufferHeight); // setting this to 1280x720 fixes the aspect ratio but still crops

glBindFramebuffer(GL_FRAMEBUFFER, frameBufferHandle);

glUseProgram(shaderPrograms[PASSTHROUGH]);

// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, horizontalFlipTextureCoordinates);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Present
glBindRenderbuffer(GL_RENDERBUFFER, renderBufferHandle);
[oglContext presentRenderbuffer:GL_RENDERBUFFER];

修改

我还在遇到问题。我已经包含了更多来源。基本上,我需要整个原始输入纹理在宽屏幕上显示,同时还将原始纹理写入磁盘。

渲染到较小的纹理时,会自动缩放内容,这与渲染缓冲区的情况不同吗?

我想我可以通过更小的纹理制作另一个直通,但这样会减慢速度。

4 个答案:

答案 0 :(得分:1)

首先,将glViewport(0, 0, renderBufferWidth, renderBufferHeight);852x640保持一致。 问题出在你的squareVertices中 - 看起来它保持代表纹理大小的坐标。您需要将其设置为等于渲染缓冲区大小。

这个想法是纹理映射到你的squareVertices rect。因此,您可以渲染任意大小的纹理映射到任何大小的矩形 - 纹理图像将缩放以适合矩形。

[更新:方形顶点]

在你的情况下应该是:

{
0.0f, (float)renderBufferWidth/frameHeight,
(float)renderBufferWidth/frameWidth, (float)renderBufferHeight/frameHeight,
0.0f,  0.0f,
(float)renderBufferWidth/frameWidth,  0.0f,
};

但这并不是一个好的解决方案。从理论上讲,屏幕上的矩形大小由顶点位置和变换矩阵决定。在屏幕上渲染之前,每个顶点都与矩阵相乘。看起来你没有设置OpenGL projection matrix。使用正确的正交投影,您的顶点应具有像素等效位置。

答案 1 :(得分:0)

因为我是OpenGL的新手,所以要记住要映射的纹理应该是2乘2的幂。 例如,图像分辨率应为... 256x256,512x512。 然后,您可以使用SCALE图像 gl.glScalef(X,Y,Z);根据您的要求进行相应的功能。 相应地获得高度和宽度,并将它们放在你的scalef函数中。 试试这个,我希望这有效。

答案 2 :(得分:0)

尝试这些功能。我可以通过info songhoa.ca.com

验证我的答案
glGenFramebuffers()
  • void glGenFramebuffers(GLsizei n,GLuint * ids)

    • 要创建的帧缓冲区数
  • void glDeleteFramebuffers(GLsizei n,const GLuint * ids)

    • 指向GLuint变量的指针或存储多个ID的数组。它返回未使用的帧缓冲区对象的ID。 ID 0表示默认的帧缓冲区,它是窗口系统提供的帧缓冲区。

glDeleteFramebuffers()不再使用时,可以删除FBO。

glBindFramebuffer()

创建FBO后,必须先绑定它才能使用它。

  • void glBindFramebuffer(GLenum target,GLuint id)

    • 第一个参数是目标应该是GL_FRAMEBUFFER。

    • 第二个参数是帧缓冲对象的ID。

绑定FBO后,所有OpenGL操作都会影响当前绑定的framebuffer对象。对象ID 0保留用于默认窗口系统提供的帧缓冲区。因此,为了解除绑定当前帧缓冲区(FBO),请在glBindFramebuffer()中使用ID 0。


尝试使用这些,或至少 visit the link ,这可以帮助你很多。对不起,我没有OpenGL经验,但我想提供链接,并解释这两个功能。我想你可以使用这些信息来编写你的代码。

答案 3 :(得分:0)

哦,小伙子,所以答案是这一直在起作用;)事实证明,iPhone 4上的高分辨率预设模式实际上覆盖的区域比中等分辨率的预设更少。这让我陷入了一个循环,直到Brigadir一直提出我应该做的事情,检查GPU快照。

我也通过在GPUImage框架中破解适当的代码来找出宽高比问题。 https://github.com/bradLarson/GPUImage