Rendu à la texture, puis rendre la texture à l'écran dans iOS

J'essaye de rendre une scène simple dans un FBO qui est soutenu par une texture comme pièce jointe de couleur et puis dessine un quadruplé à l'écran en utilisant cette texture dans iOS. Cela m'aidera à faire du post-traitement de la scène finale. Il y a quelques questions sur SO qui répondent à des questions similaires (mais pas tout à fait les mêmes) et j'ai essayé tout ce que je pouvais comprendre. Rien ne fonctionne.

J'ai deux programmes de shader. Le premier _program prend simplement les positions de vertex et les rend avec une seule couleur. Le second quadProgram prend une texture, les coords de texture et les coords quadruples. (Dans l'intérêt de la brièveté, j'omets le code pour ces shaders.)

Les deux shaders fonctionnent correctement. Ils produisent indépendamment des résultats corrects. Cependant, lorsque j'essaie de rendre la "texture rendue" au quad plutôt que d'utiliser un échantillon de texture de bois, j'ai simplement un écran noir. Voici les bits de code pertinents. Je configure tout comme ça:

 - (void)setupGL { [EAGLContext setCurrentContext:self.context]; _program = [self createProgramWithVertexShader:@"Shader" fragShader:@"Shader"]; GLuint GLKVertexAtsortingbPosition = glGetAtsortingbLocation(_program, "position"); quadProgram = [self createProgramWithVertexShader:@"PostShader" fragShader:@"PostShader"]; quadTexCoord = glGetAtsortingbLocation(quadProgram, "a_texcoord"); quadPosition = glGetAtsortingbLocation(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); glEnableVertexAtsortingbArray(GLKVertexAtsortingbPosition); glVertexAtsortingbPointer(GLKVertexAtsortingbPosition, 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; NSSsortingng *filePath = [[NSBundle mainBundle] pathForResource:@"wood_floor_256" ofType:@"jpg"]; // 1 spriteTexture = [GLKTextureLoader textureWithContentsOfFile:filePath options:nil error:&theError]; // 2 } 

Et puis ma boucle principale:

 - (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 glVertexAtsortingbPointer(quadPosition, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), quadPositions); glVertexAtsortingbPointer(quadTexCoord, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), quadTexcoords); // ensure the proper arrays are enabled glEnableVertexAtsortingbArray(quadPosition); glEnableVertexAtsortingbArray(quadTexCoord); // draw glDrawArrays(GL_TRIANGLES, 0, 2*3); } 

Je ne sais même pas comment dire si la texture support contient l'écran rendu.

La partie render to texture devrait rendre dans le FBO ce qui suit: Rendu iPad

Si je remplace les deux lignes:

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

avec

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

Je reçois ce qui suit:

ipadwood

Ce qui indique que le code pour rendre un quad à l'écran avec une texture est correct.

Je n'ai aucune idée de comment get le premier écran rendu au quad.

Puisque la texture que vous utilisez est NPOT, il faut un paramètre d'enroulement qui ne soit pas par défaut.

Ajoutez le droit suivant sous l'autre appel glTexParameteri. Cela devrait résoudre le problème:

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