2

我有一个 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

4 回答 4

2

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

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

[更新:方形顶点]

在您的情况下,它应该是:

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

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

于 2012-09-18T06:51:51.227 回答
0

由于我是 OpenGL 的新手,记得要映射的纹理应该是 2 乘 2 的幂。例如,图像分辨率应该是...... 256x256、512x512。然后您可以使用 gl.glScalef(x,y,z); 缩放图像 根据您的要求相应地发挥作用。相应地获取高度和宽度并将它们放入您的 scalef 函数中。试试这个,我希望这有效。

于 2012-09-19T19:37:45.023 回答
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 目标,GLuint id)

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

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

一旦绑定了 FBO,所有 OpenGL 操作都会影响当前绑定的帧缓冲区对象。对象 ID 0 是为默认窗口系统提供的帧缓冲区保留的。因此,为了取消绑定当前帧缓冲区(FBO),请在glBindFramebuffer().


尝试使用这些,或者至少访问对您有很大帮助的链接。抱歉,我在 OpenGL 方面没有经验,但我想提供链接,并解释这 2 个功能。我认为您可以使用这些信息来编写代码。

于 2012-09-24T03:22:22.093 回答
0

哦,男孩,所以答案是这一直有效;)事实证明,iPhone 4 上的高分辨率预设模式实际上比中等分辨率预设覆盖的区域更少。这让我陷入了一个循环,直到 Brigadir 建议我应该首先做什么,检查 GPU 快照。

我也通过破解 GPUImage 框架中的适当代码来解决纵横比问题。https://github.com/bradLarson/GPUImage

于 2012-09-25T09:20:49.870 回答