渲染到纹理,然后在iOS中将纹理渲染到屏幕

时间:2014-03-21 00:56:42

标签: ios objective-c opengl-es xcode5

我正在尝试将一个简单的场景渲染到一个由纹理作为颜色附件支持的FBO中,然后在iOS中使用此纹理将四边形绘制到屏幕上。 这将帮助我对最终场景进行一些后期处理。关于SO的一些问题涉及类似(但不完全相同)的问题,我已经尝试过任何我能理解的问题。什么都行不通。

我有两个着色器程序。第一个_program只取顶点位置并用单一颜色渲染它们。第二个quadProgram采用纹理,纹理坐标和四边形坐标。 (为了简洁起见,我省略了这些着色器的代码。)

两个着色器都能正常工作。他们独立产生正确的结果。但是,当我尝试将“渲染纹理”渲染到四边形而不是使用样本木材纹理时,我只是得到一个黑色屏幕。以下是相关的代码位。我设置了所有类似的东西:

- (void)setupGL
{
    [EAGLContext setCurrentContext:self.context];

    _program = [self createProgramWithVertexShader:@"Shader" fragShader:@"Shader"];
    GLuint GLKVertexAttribPosition = glGetAttribLocation(_program, "position");

    quadProgram = [self createProgramWithVertexShader:@"PostShader" fragShader:@"PostShader"];
    quadTexCoord = glGetAttribLocation(quadProgram, "a_texcoord");
    quadPosition = glGetAttribLocation(quadProgram, "a_position");
    diffuseTexture = glGetUniformLocation(quadProgram, "s_diffuse");

    glEnable(GL_DEPTH_TEST);

    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));

    glBindVertexArrayOES(0);

    // ============
    // ---- for render to texture
    width = self.view.bounds.size.width;
    height = self.view.bounds.size.height;

    // create fbo
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

    // create and attach backing texture
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

    // create and attach depthbuffer
    glGenRenderbuffers(1, &depthRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);

    // Check if framebuffer was loaded correctly
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
    if(status != GL_FRAMEBUFFER_COMPLETE) {
        NSLog(@"failed to make complete framebuffer object %x", status);
    }

    // sample texture
    NSError *theError;

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"wood_floor_256" ofType:@"jpg"]; // 1

    spriteTexture = [GLKTextureLoader textureWithContentsOfFile:filePath options:nil error:&theError]; // 2
}

然后是我的主循环:

- (void)update
{
    // First save the default frame buffer.
    static GLint default_frame_buffer = 0;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &default_frame_buffer);

    // render to texture
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindVertexArrayOES(_vertexArray);

    glUseProgram(_program);

    glDrawArrays(GL_TRIANGLES, 0, 36);

    // render to screen
    glBindFramebuffer(GL_FRAMEBUFFER, default_frame_buffer);
    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(quadProgram);

    const float quadPositions[] = {  1.0,  1.0, 0.0,
        -1.0,  1.0, 0.0,
        -1.0, -1.0, 0.0,
        -1.0, -1.0, 0.0,
        1.0, -1.0, 0.0,
        1.0,  1.0, 0.0 };
    const float quadTexcoords[] = { 1.0, 1.0,
        0.0, 1.0,
        0.0, 0.0,
        0.0, 0.0,
        1.0, 0.0,
        1.0, 1.0 };

    // stop using VBO and other bufs.
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArrayOES(0);

    glBindTexture(GL_TEXTURE_2D, texture);
    glActiveTexture(GL_TEXTURE_2D);

    // setup buffer offsets
    glVertexAttribPointer(quadPosition, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), quadPositions);
    glVertexAttribPointer(quadTexCoord, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), quadTexcoords);

    // ensure the proper arrays are enabled
    glEnableVertexAttribArray(quadPosition);
    glEnableVertexAttribArray(quadTexCoord);

    // draw
    glDrawArrays(GL_TRIANGLES, 0, 2*3);
}

我甚至不知道如何判断支持texture是否包含渲染的屏幕。

渲染到纹理部分应该渲染到FBO中: iPad render

如果我更换两行:

    glBindTexture(GL_TEXTURE_2D, texture);
    glActiveTexture(GL_TEXTURE_2D);

glBindTexture(spriteTexture.target, spriteTexture.name);
glEnable(spriteTexture.target);

我得到以下内容:

ipadwood

这表示使用纹理渲染四边形到屏幕的代码是正确的。

我不知道如何将第一个屏幕渲染到四边形。

1 个答案:

答案 0 :(得分:1)

由于您使用的纹理是NOT,因此需要非默认的wrap参数。

在另一个glTexParameteri调用下面添加以下内容。它应该解决问题:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);