Не работает stencil в Java Android Opengl es 2.0

В android opengl es 2.0 стандартным рендерером (наследник GLSurfaceView.Renderer) рисую сцену

@Override
public void onDrawFrame(GL10 gl10)
{
        GLES20.glEnable(GLES20.GL_STENCIL_TEST);
        GLES20.glClearStencil(1);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);


        glStencilMask(0x00);

        shaderTexture2.useProgram();

        GLES20.glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GLES20.GL_REPLACE);
        GLES20. glStencilFunc(GLES20.GL_ALWAYS, 1, 0xFF);
        GLES20.glStencilMask(0xFF);

        //1 рисуем узкий треугольник
        shaderTexture2.draw(buf_slim, mvp, mLightPosInEyeSpace, tex1);


        GLES20.glStencilFunc(GLES20.GL_NOTEQUAL, 1, 0xFF);
        GLES20.glStencilMask(0x00);

        //2 рисуем большой треугольник
        shaderTexture2.draw(buf_big, mvp, mLightPosInEyeSpace, tex1);

        GLES20.glStencilMask(0xFF);

}

Если в первой строке метода не включать GLES20.glEnable(GLES20.GL_STENCIL_TEST); то будут рисоваться оба треугольника: синий и полосатый (первая картинка). Если стенсил включить то я ожидаю что на шаге 1, при отрисовке полосатого треугольника будет заполнен единицами буфер трафарета, а на шаге 2 синий обрежется и будет выведен только в то место где были единицы от первого шага (вторая картинка). А на самом деле при включенном стенсиле рисуется просто узкий полосатый треугольник а вовсе никакой не обрезанный синий (третья картинка). Какие и когда функции и маски стенсила включать, чтобы рисовалось, как я ожидаю?

без включенного стенсила вот такое ожидаю

а на самом деле вот такое


Ответы (1 шт):

Автор решения: woesss
@Override
public void onDrawFrame(GL10 gl10) {
    GLES20.glEnable(GLES20.GL_STENCIL_TEST);
    // мы же будем писать единицы, значит изначально их в буфере быть не должно
    GLES20.glClearStencil(0);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);


    glStencilMask(0x00);

    shaderTexture2.useProgram();

    // мы не хотим рисовать сам треугольник, а только заполнить трафарет
    // потому тест трафарета должен быть провальным
    GLES20. glStencilFunc(GLES20.GL_NEVER, 1, 0xFF);

    // соответственно запись в сам буфер должна быть при провале теста трафарета
    GLES20.glStencilOp(GLES20.GL_REPLACE, GLES20.GL_KEEP, GLES20.GL_KEEP);
    GLES20.glStencilMask(0xFF);

    //1 рисуем узкий треугольник
    shaderTexture2.draw(buf_slim, mvp, mLightPosInEyeSpace, tex1);

    // тест должен быть пройден только там, где единицы
    GLES20.glStencilFunc(GLES20.GL_EQUAL, 1, 0xFF);
    GLES20.glStencilMask(0x00);

    //2 рисуем большой треугольник
    shaderTexture2.draw(buf_big, mvp, mLightPosInEyeSpace, tex1);

    GLES20.glStencilMask(0xFF);
}

В учебнике эта тема достаточно разжёвана: http://www.opengl.org.ru/books/open_gl/chapter4.12.html.

P.S. я может что-то пропустил или забыл, например отключить тест глубины, так как не известно какие координаты у ваших треугольников.
Так же не помню как инициализируется контекст в GLSurfaceView - убедитесь что трафаретный буфер вообще создан.

→ Ссылка