Uso de OpenGL ES 2.0 FrameBuffer (FBO) y Stencil en android Código nativo (ndk)

Estoy intentando generar un objeto de frambuffer y utilizar la plantilla dentro de una aplicación androide nativa usando el NDK (r5b). El dispositivo de destino está ejecutando froyo 2.2, que soporta OpenGL ES 2.0.

Por lo tanto, he estado codificando mucho código gl en mis bibliotecas nativas de c ++ y no he tenido ningún problema excepto por esto. Simplemente no puedo hacer que funcione.

He aquí un snipplet de código para la creación de framebuffer. Completness es todo bueno, pero la pantalla sigue siendo completamente negro. Es como el fbo que estoy creando no está realmente ligado a la superficie gl que es creado por la parte de Java de la aplicación. El resto del código de mi aplicación es bueno, si elimino la creación y la vinculación de fbo, todo funciona perfectamente, excepto que no tengo las plantillas de trabajo que necesito para mi aplicación.

GLint backingWidth = 1024; GLint backingHeight = 1024; //Create the FrameBuffer and binds it glGenFramebuffers(1, &_defaultFramebuffer); checkGlError("glGenFramebuffers"); glBindFramebuffer(GL_FRAMEBUFFER, _defaultFramebuffer); checkGlError("glBindFramebuffer"); //Create the RenderBuffer for offscreen rendering // Color glGenRenderbuffers(1, &_colorRenderbuffer); checkGlError("glGenRenderbuffers color"); glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderbuffer); checkGlError("glBindRenderbuffer color"); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, backingWidth, backingHeight); checkGlError("glRenderbufferStorage color"); //Create the RenderBuffer for offscreen rendering // Depth glGenRenderbuffers(1, &_depthRenderbuffer); checkGlError("glGenRenderbuffers depth"); glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer); checkGlError("glBindRenderbuffer depth"); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, backingWidth, backingHeight); checkGlError("glRenderbufferStorage depth"); //Create the RenderBuffer for offscreen rendering // Stencil glGenRenderbuffers(1, &_stencilRenderbuffer); checkGlError("glGenRenderbuffers stencil"); glBindRenderbuffer(GL_RENDERBUFFER, _stencilRenderbuffer); checkGlError("glBindRenderbuffer stencil"); glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, backingWidth, backingHeight); checkGlError("glRenderbufferStorage stencil"); // bind renderbuffers to framebuffer object glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer); checkGlError("glFramebufferRenderbuffer depth"); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderbuffer); checkGlError("glFramebufferRenderbuffer color"); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _stencilRenderbuffer); checkGlError("glFramebufferRenderbuffer stencil"); //Test for FrameBuffer completeness GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); checkGlError("glCheckFramebufferStatus"); switch (status) { case GL_FRAMEBUFFER_COMPLETE: LOGI("\n\n\nFLIPBOOM : FBO complete GL_FRAMEBUFFER_COMPLETE %x\n\n\n", status);break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: LOGI("\n\n\nFLIPBOOM : FBO GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT %x\n\n\n", status);break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: LOGI("\n\n\nFLIPBOOM : FBO FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT %x\n\n\n", status);break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: LOGI("\n\n\nFLIPBOOM : FBO FRAMEBUFFER_INCOMPLETE_DIMENSIONS %x\n\n\n", status);break; case GL_FRAMEBUFFER_UNSUPPORTED: LOGI("\n\n\nFLIPBOOM : FBO GL_FRAMEBUFFER_UNSUPPORTED %x\n\n\n", status);break; default : LOGI("\n\n\nFLIPBOOM : failed to make complete framebuffer object %x\n\n\n", status); } 

También he intentado renderizar a una textura 2D en lugar del renderbuffer … tampoco funcionó.

Así que, ¿hay alguna manera de arreglar esto? ¿Estoy haciendo algo mal aquí? Si alguien tiene alguna idea por favor lemme saber …. ha estado pasando mucho tiempo buscando este problema … jeje;)

Gracias por adelantado !

Saludos!


EDIT:

Ok, he logrado que el buffer de la plantilla funcione pero las FBO no funcionan. Creo que OpenGL ES 2.0 no es totalmente compatible con Android (utilizando r5b aquí btw). Creo que los stubs de métodos se definen, pero no se implementan completamente. O bien, el GlSurfaceView creado no se enlaza correctamente con las FBO.

En cuanto al buffer de stencil, tuve que hacer

 glEnable(GL_DEPTH_TEST); 

Y eliminar el uso de glDepthMask para que funcionen correctamente.

@ Zennichimaro, Para el uso de buffer stencil!

Durante la inicialización:

 glBindFramebuffer(GL_FRAMEBUFFER, 0); glEnable(GL_DEPTH_TEST); 

Durante la renderización:

 glViewport(0, 0, GetViewWidth(), GetViewHeight()); checkGlError("glViewport"); if (_firstRenderDone == false) { glClearDepthf( 0.9f ); glDepthMask( GL_TRUE ); glClear( GL_DEPTH_BUFFER_BIT ); glDepthMask( GL_FALSE ); _firstRenderDone = true; } glClearColor(M_channelToFloat(_backgroundColor.r), M_channelToFloat(_backgroundColor.g), M_channelToFloat(_backgroundColor.b), M_channelToFloat(_backgroundColor.a)); checkGlError("glClearColor"); glClearStencil( 0 ); checkGlError("glClearStencil"); glClear( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); checkGlError("glClear"); _stencilLayer = 1; //use our custom shaders if( _program ) { glUseProgram(_program); if( transformMatrix3x3 != NULL ) { glUniformMatrix3fv( _uniforms[OGL_UNIFORM_TRANSFORM], 1, false, transformMatrix3x3 ); } // reset the shading. glUniform1f( _uniforms[ OGL_UNIFORM_SHADE ], 0.0f ); } //Do the actual drawing (Triangle Slip) if( object ) { _isRender = true; object->OglDraw(this); _isRender = false; } 

Cuando necesito utilizar el stencil, utilizo los siguientes métodos dependiendo de lo que necesito:

 void GlEs2Renderer::StencilStartMask() { if (!USE_STENCIL) //For debugging purpose return; glEnable(GL_STENCIL_TEST); //Turn off writing to the Color Buffer and Depth Buffer //We want to draw to the Stencil Buffer only glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); //Set 1 into the stencil buffer glStencilFunc( GL_ALWAYS, NewStencilLayer(), 0xFFFFFFFF ); glStencilOp( GL_ZERO, GL_ZERO, GL_REPLACE ); } void GlEs2Renderer::StencilUseMask() { if (!USE_STENCIL) //For debugging purpose return; //Turn back on Color Buffer and Depth Buffer glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); //Only write to the Stencil Buffer where 1 is set glStencilFunc( GL_EQUAL, StencilLayer(), 0xFFFFFFFF); //Keep the content of the Stencil Buffer glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); } void GlEs2Renderer::StencilOverlayMask() { if (!USE_STENCIL) //For debugging purpose return; //Turn back on Color Buffer and Depth Buffer glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); glDepthMask(true); //Only write to the Stencil Buffer where 1 is set glStencilFunc( GL_EQUAL, StencilLayer(), 0xFFFFFFFF); //Keep the content of the Stencil Buffer and increase when z passed glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); } 

Y finalmente hago la técnica de doble pase para dibujar dentro de la plantilla … He aquí un ejemplo:

 glVertexAttribPointer(OGL_ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, _triangles); glEnableVertexAttribArray(OGL_ATTRIB_VERTEX); glVertexAttribPointer(OGL_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, 1, 0, _colors); glEnableVertexAttribArray(OGL_ATTRIB_COLOR); glContext->StencilStartMask(); glDrawArrays(GL_TRIANGLE_STRIP, 0, _nPoints); glContext->StencilUseMask();; glDrawArrays(GL_TRIANGLE_STRIP, 0, _nPoints); glContext->StencilEndMask(); 

Mi código es bastante complejo por lo que es difícil publicar sólo lo que está relacionado con la plantilla, pero espero que ayude;)

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.