OpenGL ES 2.0 - iOS - 使用 FBO 渲染到纹理

Posted

技术标签:

【中文标题】OpenGL ES 2.0 - iOS - 使用 FBO 渲染到纹理【英文标题】:OpenGL ES 2.0 - iOS - Render to texture using FBO 【发布时间】:2015-07-30 20:10:58 【问题描述】:

根据教程:

“http://www.raywenderlich.com/4404/opengl-es-2-0-for-iphone-tutorial-part-2-textures”

还有《Open GL ES 2.0 Programming Guide》一书

我正在尝试将场景渲染为 FBO 纹理,然后在显示窗口上渲染该 FBO 纹理。

我不知道为什么,但我有一个白屏..

编辑 1:白屏是由于在渲染循环中绑定了深度缓冲区。现在的问题是FBO纹理中渲染的立方体没有渲染到屏幕上..

编辑 2:更新代码并添加着色器文件

这是我的代码:

OpenGLView.h:

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>

@interface OpenGLView : UIView 
    CAEAGLLayer* _eaglLayer;
    EAGLContext* _context;

    GLuint _viewFrameBuffer;
    GLuint _colorRenderBuffer;
    GLuint _depthRenderBuffer;



    float _cubeCurrentRotation;

    GLuint _cubeTexture;

    GLuint _cubeVertexBuffer;
    GLuint _cubeIndexBuffer;
    GLuint _viewportSizedQuadVertexBuffer;
    GLuint _viewportSizedQuadIndexBuffer;

    GLuint _FBO;
    GLuint _FBOTexture;
    GLuint _FBODepthBuffer;

    // shaders

    // simple shader
    GLuint _simpleShaderProgram;
    GLuint _simpleVertexShader;
    GLuint _simpleFragmentShader;
    GLuint _positionSlot;
    GLuint _colorSlot;
    GLuint _projectionUniform;
    GLuint _modelViewUniform;
    GLuint _texCoordSlot;
    GLuint _textureUniform;
    // texture shader
    GLuint _textureShaderProgram;
    GLuint _textureVertexShader;
    GLuint _texturePositionSlot;
    GLuint _textureColorSlot;
    GLuint _textureTexCoordSlot;
    GLuint _textureTextureUniform;


@end

OpenGLView.m:

    //
//  OpenGLView.m
//  HelloOpenGL
//
//  Created by Ray Wenderlich on 5/24/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "OpenGLView.h"
#import "CC3GLMatrix.h"

@implementation OpenGLView

typedef struct 
    float Position[3];
    float Color[4];
    float TexCoord[2];
 Vertex;

#define TEX_COORD_MAX 1

const Vertex cubeVertices[] = 
    // Front
    1, -1, 0, 1, 0, 0, 1, TEX_COORD_MAX, 0,
    1, 1, 0, 0, 1, 0, 1, TEX_COORD_MAX, TEX_COORD_MAX,
    -1, 1, 0, 0, 0, 1, 1, 0, TEX_COORD_MAX,
    -1, -1, 0, 0, 0, 0, 1, 0, 0,
    // Back
    1, 1, -2, 1, 0, 0, 1, TEX_COORD_MAX, 0,
    -1, -1, -2, 0, 1, 0, 1, TEX_COORD_MAX, TEX_COORD_MAX,
    1, -1, -2, 0, 0, 1, 1, 0, TEX_COORD_MAX,
    -1, 1, -2, 0, 0, 0, 1, 0, 0,
    // Left
    -1, -1, 0, 1, 0, 0, 1, TEX_COORD_MAX, 0,
    -1, 1, 0, 0, 1, 0, 1, TEX_COORD_MAX, TEX_COORD_MAX,
    -1, 1, -2, 0, 0, 1, 1, 0, TEX_COORD_MAX,
    -1, -1, -2, 0, 0, 0, 1, 0, 0,
    // Right
    1, -1, -2, 1, 0, 0, 1, TEX_COORD_MAX, 0,
    1, 1, -2, 0, 1, 0, 1, TEX_COORD_MAX, TEX_COORD_MAX,
    1, 1, 0, 0, 0, 1, 1, 0, TEX_COORD_MAX,
    1, -1, 0, 0, 0, 0, 1, 0, 0,
    // Top
    1, 1, 0, 1, 0, 0, 1, TEX_COORD_MAX, 0,
    1, 1, -2, 0, 1, 0, 1, TEX_COORD_MAX, TEX_COORD_MAX,
    -1, 1, -2, 0, 0, 1, 1, 0, TEX_COORD_MAX,
    -1, 1, 0, 0, 0, 0, 1, 0, 0,
    // Bottom
    1, -1, -2, 1, 0, 0, 1, TEX_COORD_MAX, 0,
    1, -1, 0, 0, 1, 0, 1, TEX_COORD_MAX, TEX_COORD_MAX,
    -1, -1, 0, 0, 0, 1, 1, 0, TEX_COORD_MAX,
    -1, -1, -2, 0, 0, 0, 1, 0, 0
;

const GLubyte cubeIndices[] = 
    // Front
    0, 1, 2,
    2, 3, 0,
    // Back
    4, 5, 6,
    6, 7, 4,
    // Left
    8, 9, 10,
    10, 11, 8,
    // Right
    12, 13, 14,
    14, 15, 12,
    // Top
    16, 17, 18,
    18, 19, 16,
    // Bottom
    20, 21, 22,
    22, 23, 20
;

const Vertex viewPortQuadVertices[] = 
    1, -1, 0, 1, 1, 1, 1, TEX_COORD_MAX, 0,
    1, 1, 0, 1, 1, 1, 1, TEX_COORD_MAX, TEX_COORD_MAX,
    -1, 1, 0, 1, 1, 1, 1, 0, TEX_COORD_MAX,
    -1, -1, 0, 1, 1, 1, 1, 0, 0
;

const GLubyte viewPortQuadIndices[] = 
    0, 1, 2,
    2, 3, 0,
;

+ (Class)layerClass 
    return [CAEAGLLayer class];


- (void)dealloc 
    [_context release];
    _context = nil;
    [super dealloc];


- (id)initWithFrame:(CGRect)frame 
    self = [super initWithFrame:frame];
    if (self) 
        [self setupLayer];
        [self setupContext];
        [self setupDepthBuffer];
        [self setupRenderBuffer];
        [self setupFrameBuffer];
        [self setupFBOs];
        [self compileShaders];
        [self setupVBOs];
        [self setupDisplayLink];
        _cubeTexture = [self setupTexture:@"tile_floor.png"];
    
    return self;


- (void)setupDisplayLink 
    CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];


- (void)setupLayer 
    _eaglLayer = (CAEAGLLayer*) self.layer;
    _eaglLayer.opaque = YES;


- (void)setupContext 
    EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
    _context = [[EAGLContext alloc] initWithAPI:api];
    if (!_context) 
        NSLog(@"Failed to initialize OpenGLES 2.0 context");
        exit(1);
    

    if (![EAGLContext setCurrentContext:_context]) 
        NSLog(@"Failed to set current OpenGL context");
        exit(1);
    


- (void)setupRenderBuffer 
    glGenRenderbuffers(1, &_colorRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];


- (void)setupDepthBuffer 
    glGenRenderbuffers(1, &_depthRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, self.frame.size.width, self.frame.size.height);


- (void)setupFrameBuffer 
    glGenFramebuffers(1, &_viewFrameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _viewFrameBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);


-(void)setupFBOs 
    GLint maxRenderBufferSize;
    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxRenderBufferSize);

    GLuint textureWidth = self.frame.size.width;
    GLuint textureHeight = self.frame.size.height;

    if(maxRenderBufferSize <= textureWidth
       || maxRenderBufferSize <= textureHeight) 
            NSLog(@"FBO cant allocate that much space");
    

    glGenFramebuffers(1, &_FBO);
    glGenRenderbuffers(1, &_FBODepthBuffer);
    glGenTextures(1, &_FBOTexture);

    glBindTexture(GL_TEXTURE_2D, _FBOTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureWidth, textureHeight,
                 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 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);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glBindRenderbuffer(GL_RENDERBUFFER, _FBODepthBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, textureWidth, textureHeight);

    glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _FBOTexture, 0);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _FBODepthBuffer);

    GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if(status != GL_FRAMEBUFFER_COMPLETE) 
        NSLog(@"FBO is not complete :%u", status);
    


- (GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType 
    NSString* shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:@"glsl"];
    NSError* error;
    NSString* shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
    if (!shaderString) 
        NSLog(@"Error loading shader: %@", error.localizedDescription);
        exit(1);
    

    GLuint shaderHandle = glCreateShader(shaderType);

    const char * shaderStringUTF8 = [shaderString UTF8String];
    int shaderStringLength = [shaderString length];
    glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);

    glCompileShader(shaderHandle);

    GLint compileSuccess;
    glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
    if (compileSuccess == GL_FALSE) 
        GLchar messages[256];
        glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    

    return shaderHandle;


- (void)compileShaders 
    _simpleVertexShader = [self compileShader:@"SimpleVertex" withType:GL_VERTEX_SHADER];
    _simpleFragmentShader = [self compileShader:@"SimpleFragment" withType:GL_FRAGMENT_SHADER];
    _textureVertexShader = [self compileShader:@"TextureVertex" withType:GL_VERTEX_SHADER];

    _simpleShaderProgram = glCreateProgram();
    glAttachShader(_simpleShaderProgram, _simpleVertexShader);
    glAttachShader(_simpleShaderProgram, _simpleFragmentShader);
    glLinkProgram(_simpleShaderProgram);

    GLint linkSuccess;
    glGetProgramiv(_simpleShaderProgram, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE) 
        GLchar messages[256];
        glGetProgramInfoLog(_simpleShaderProgram, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    

    glUseProgram(_simpleShaderProgram);

    _positionSlot = glGetAttribLocation(_simpleShaderProgram, "Position");
    _colorSlot = glGetAttribLocation(_simpleShaderProgram, "SourceColor");
    glEnableVertexAttribArray(_positionSlot);
    glEnableVertexAttribArray(_colorSlot);

    _projectionUniform = glGetUniformLocation(_simpleShaderProgram, "Projection");
    _modelViewUniform = glGetUniformLocation(_simpleShaderProgram, "Modelview");

    _texCoordSlot = glGetAttribLocation(_simpleShaderProgram, "TexCoordIn");
    glEnableVertexAttribArray(_texCoordSlot);
    _textureUniform = glGetUniformLocation(_simpleShaderProgram, "Texture");


    // Texture shader
    _textureShaderProgram = glCreateProgram();
    glAttachShader(_textureShaderProgram, _textureVertexShader);
    glAttachShader(_textureShaderProgram, _simpleFragmentShader);
    glLinkProgram(_textureShaderProgram);

    glGetProgramiv(_textureShaderProgram, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE) 
        GLchar messages[256];
        glGetProgramInfoLog(_textureShaderProgram, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    

    glUseProgram(_textureShaderProgram);

    _texturePositionSlot = glGetAttribLocation(_textureShaderProgram, "texPosition");
    _textureColorSlot = glGetAttribLocation(_textureShaderProgram, "texSourceColor");
    glEnableVertexAttribArray(_texturePositionSlot);
    glEnableVertexAttribArray(_textureColorSlot);

    _textureTexCoordSlot = glGetAttribLocation(_textureShaderProgram, "texTexCoordIn");
    glEnableVertexAttribArray(_textureTexCoordSlot);
    _textureTextureUniform = glGetUniformLocation(_textureShaderProgram, "Texture");


- (void)setupVBOs 
    glGenBuffers(1, &_cubeVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _cubeVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_cubeIndexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _cubeIndexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);

    glGenBuffers(1, &_viewportSizedQuadVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _viewportSizedQuadVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(viewPortQuadVertices), viewPortQuadVertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_viewportSizedQuadIndexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _viewportSizedQuadIndexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(viewPortQuadIndices), viewPortQuadIndices, GL_STATIC_DRAW);


- (GLuint)setupTexture:(NSString *)fileName 
    CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
    if (!spriteImage) 
        NSLog(@"Failed to load image %@", fileName);
        exit(1);
    

    size_t width = CGImageGetWidth(spriteImage);
    size_t height = CGImageGetHeight(spriteImage);

    GLubyte * spriteData = (GLubyte *) calloc(width*height*4, sizeof(GLubyte));

    CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);

    CGContextRelease(spriteContext);

    GLuint texName;
    glGenTextures(1, &texName);
    glBindTexture(GL_TEXTURE_2D, texName);

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

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);

    free(spriteData);
    return texName;


- (void)render:(CADisplayLink*)displayLink 

    glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
    //glBindRenderbuffer(GL_RENDERBUFFER, _FBODepthBuffer);

    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    glClearColor(255.0/255.0, 255.0/255.0, 255.0/255.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);

    glViewport(0, 0, self.frame.size.width, self.frame.size.height);

    glUseProgram(_simpleShaderProgram);

    // Cube draw in FBO
    CC3GLMatrix *projection = [CC3GLMatrix matrix];
    float h = 4.0f * self.frame.size.height / self.frame.size.width;
    [projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:1000];
    glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);

    CC3GLMatrix *modelView = [CC3GLMatrix matrix];
    [modelView populateFromTranslation:CC3VectorMake(sin(CACurrentMediaTime()), 0, -7)];
    _cubeCurrentRotation += displayLink.duration * 90;
    [modelView rotateBy:CC3VectorMake(_cubeCurrentRotation, _cubeCurrentRotation, 0)];
    glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);

    glBindBuffer(GL_ARRAY_BUFFER, _cubeVertexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _cubeIndexBuffer);

    glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
    glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));

    glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _cubeTexture);
    glUniform1i(_textureUniform, 0);

    glDrawElements(GL_TRIANGLES, sizeof(cubeIndices)/sizeof(cubeIndices[0]), GL_UNSIGNED_BYTE, 0);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // ---------------------------------------------------------------
    // FBO -> window

    glBindFramebuffer(GL_FRAMEBUFFER, _viewFrameBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);

    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    glClearColor(0.0/255.0, 0.0/255.0, 0.0/255.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);

    glViewport(0, 0, self.frame.size.width, self.frame.size.height);

    glUseProgram(_textureShaderProgram);

    glBindBuffer(GL_ARRAY_BUFFER, _viewportSizedQuadVertexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _viewportSizedQuadIndexBuffer);

    glVertexAttribPointer(_texturePositionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
    glVertexAttribPointer(_textureColorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));

    glVertexAttribPointer(_textureTexCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _FBOTexture);
    glUniform1i(_textureTextureUniform, 0);
    glDrawElements(GL_TRIANGLES, sizeof(viewPortQuadIndices)/sizeof(viewPortQuadIndices[0]), GL_UNSIGNED_BYTE, 0);

    [_context presentRenderbuffer:GL_RENDERBUFFER];

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);


@end

SimpleVertex.glsl:

attribute vec4 Position; 
attribute vec4 SourceColor; 

varying vec4 DestinationColor; 

uniform mat4 Projection;
uniform mat4 Modelview;

attribute vec2 TexCoordIn;
varying vec2 TexCoordOut;

void main(void)  
    DestinationColor = SourceColor; 
    gl_Position = Projection * Modelview * Position;
    TexCoordOut = TexCoordIn;

TextureVertex.glsl:

attribute vec4 texPosition;
attribute vec4 texSourceColor;

varying vec4 DestinationColor;

attribute vec2 texTexCoordIn;
varying vec2 TexCoordOut;

void main(void)  
    DestinationColor = texSourceColor;
    gl_Position = texPosition;
    TexCoordOut = texTexCoordIn;

SimpleFragment.glsl:

varying lowp vec4 DestinationColor;

varying lowp vec2 TexCoordOut;
uniform sampler2D Texture;

void main(void) 
    gl_FragColor = DestinationColor * texture2D(Texture, TexCoordOut);

【问题讨论】:

你尝试过什么调试?您是否尝试仅使用颜色清除缓冲区? 您可以尝试将颜色缓冲区直接传送到默认帧缓冲区,请参见此处:opengl.org/sdk/docs/man3/xhtml/glBlitFramebuffer.xml @dari :据我所知,es 2.0 中没有可用的 glBlitFramebuffer。 @FelixK。 : 谢谢,我意识到渲染过程中的这一行不是一个好主意:glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);现在我不再有黑屏了,但是没有应用 FBO 纹理,或者它是空的。请问还有其他想法吗?非常感谢您的帮助 我建议尝试逐步减少可能的错误源的数量,或者甚至更好地从一个小代码开始,并尝试仅将颜色渲染到窗口中,例如 FBO。我看到的是您还绑定了其他渲染缓冲区,例如在删除的行中,您是否删除了它们?您是否检查过用于渲染对象的代码是否正常工作?为了确定,我会在主帧缓冲区上尝试一下。 【参考方案1】:

好的,感谢@FelixK,我通过更正视口而不绑定渲染循环中的深度缓冲区解决了这个问题!

【讨论】:

以上是关于OpenGL ES 2.0 - iOS - 使用 FBO 渲染到纹理的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES 2.0 (iOS) 中的 2D 绘图

使用 OpenGL ES 2.0 和 cmake 生成 iOS 静态库

OpenGL ES 2.0 Framebuffer 渲染到纹理 iOS:没有显示

iOS OpenGL ES 2.0 GLKit GLKMatrix4 触摸结束后旋转

iOS OpenGL ES 2.0 VBO 混淆

无法让 Stencil Buffer 在 iOS 4+ 中工作(5.0 工作正常)。 [OpenGL ES 2.0]