Pergunta

Estou tentando gerar um objeto frambuffer e usar stencil dentro de um aplicativo Android nativo usando o NDK (r5b).O dispositivo de destino está executando o froyo 2.2, com suporte para OpenGL ES 2.0.

Então, tenho codificado muitos códigos gl em minhas bibliotecas nativas c++ e não tive nenhum problema, exceto este.Eu simplesmente não consigo fazer isso funcionar.

Aqui está um trecho de código para a criação do framebuffer.A integridade é boa, mas a tela permanece completamente preta.É como se o fbo que estou criando não estivesse realmente vinculado à superfície gl criada pela parte Java do aplicativo.O resto do código do meu aplicativo está bom, se eu remover a criação e ligação do fbo, tudo funcionará perfeitamente bem, exceto que não tenho os estênceis necessários para meu aplicativo funcionando.

    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);
    }

Também tentei renderizar para uma textura 2D em vez do renderbuffer... também não funcionou.

Então, existe uma maneira de consertar isso?Estou entendendo algo errado aqui?Se alguém tiver alguma idéia, por favor me avise... tenho gasto muito tempo procurando esse problema... hehe;)

Desde já, obrigado !

Saúde !


EDITAR:

Ok, consegui fazer o buffer de estêncil funcionar, mas o FBO simplesmente não está funcionando.Acho que OpenGL ES 2.0 não é totalmente compatível com Android (usando r5b aqui, aliás).Acho que os stubs de método estão definidos, mas não totalmente implementados.Ou o GlSurfaceView criado não se vincula corretamente aos FBOs.

Quanto ao buffer de estêncil, tive que fazer

glEnable(GL_DEPTH_TEST);

e remova o uso de glDepthMask para que funcionem corretamente.

Foi útil?

Solução

@ Zennichimaro, Para o uso do buffer de estêncil!

Durante a inicialização:

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

Durante a renderização:

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;
  }

Quando preciso usar stencil eu uso os seguintes métodos dependendo do que preciso:

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);
}

E por fim faço a técnica de passagem dupla para desenhar dentro do stencil...Aqui está um exemplo:

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();

Meu código é bastante complexo, então é difícil postar apenas o que está relacionado ao estêncil, mas espero que ajude;)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top