Render to texture, then render texture to screen in iOS
我正在尝试将一个简单的场景渲染到一个 FBO 中,该 FBO 由作为颜色附件的纹理支持,然后在 iOS 中使用此纹理在屏幕上绘制一个四边形。
这将帮助我对最终场景进行一些后期处理。 SO上有一些问题可以解决类似(但不完全相同)的问题,我已经尝试了我能理解的任何东西。没有任何效果。
我有两个着色器程序。第一个
两个着色器都能正常工作。他们独立地产生正确的结果。但是,当我尝试将"渲染纹理"渲染到四边形而不是使用样本木材纹理时,我只是得到一个黑屏。这是相关的代码位。我像这样设置一切:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | - (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 } |
然后是我的主循环:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | - (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); } |
我什至不知道如何判断支持
渲染到纹理部分应该渲染到 FBO 中:
如果我替换这两行:
1 2 | glBindTexture(GL_TEXTURE_2D, texture); glActiveTexture(GL_TEXTURE_2D); |
与
1 2 | glBindTexture(spriteTexture.target, spriteTexture.name); glEnable(spriteTexture.target); |
我得到以下信息:
这表明使用纹理将四边形渲染到屏幕的代码是正确的。
我不知道如何将第一个屏幕渲染到四边形。
由于你使用的纹理不是,它需要一个非默认的包裹参数。
在另一个 glTexParameteri 调用下方添加以下内容。它应该可以解决问题:
1 2 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |