Использование OpenGL ES 2.0 FrameBuffer (FBO) и трафарета в Android нативный код (ndk) - PullRequest
5 голосов
/ 13 мая 2011

Я пытаюсь сгенерировать объект мошенничества и использовать трафарет внутри собственного приложения для Android с использованием NDK (r5b). Целевое устройство работает под управлением froyo 2.2, поддерживает OpenGL ES 2.0.

Итак, я кодировал множество кодов gl в своих родных библиотеках c ++ и не столкнулся с какими-либо проблемами, кроме этого. Кажется, я просто не могу заставить это работать.

Вот фрагмент кода для создания кадрового буфера. Полнота все хорошо, но экран остается полностью черным. Это похоже на то, что созданное мной fbo на самом деле не связано с поверхностью gl, созданной Java-частью приложения. Остальная часть кода моего приложения хороша, если я удаляю создание и привязку fbo, все работает отлично, за исключением того, что у меня не работают трафареты, которые мне нужны для моего приложения.

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

Я также пытался рендерить 2D-текстуру вместо рендеринга буфера ... тоже не сработало.

Итак, есть ли способ, как я могу это исправить? Я что-то здесь не так понимаю? Если у кого-то есть идеи, пожалуйста, дайте мне знать .... слишком много времени потратили на поиск этой проблемы ... хе-хе;)

Заранее спасибо!

Ура!


РЕДАКТИРОВАТЬ:

Хорошо, мне удалось заставить работать трафаретный буфер, но FBO просто не работают. Я думаю, что OpenGL ES 2.0 не полностью поддерживается Android (используя r5b здесь, кстати). Я думаю, что заглушки метода определены, но не полностью реализованы. Или созданный GlSurfaceView неправильно связывается с FBO.

Что касается буфера трафарета, я должен был сделать

glEnable(GL_DEPTH_TEST);

и удалите использование glDepthMask, чтобы они работали правильно.

1 Ответ

3 голосов
/ 09 июня 2011

@ Zennichimaro, Для использования буфера трафарета!

Во время инициализации:

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

Во время рендеринга:

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

Когда мне нужно использовать трафарет Iв зависимости от того, что мне нужно, используйте следующие методы:

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

И, наконец, я делаю технику двойного прохода для рисования внутри трафарета ... Вот пример:

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

Мой коддовольно сложный, поэтому трудно публиковать только то, что связано с трафаретом, но я надеюсь, что это поможет;)

...