Не работает трафарет в Java Android OpenGLES ES 2.0 - PullRequest
0 голосов
/ 07 марта 2020

В 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 step. draw red triangle
        shaderTexture2.draw(buf_slim, mvp, mLightPosInEyeSpace, tex1);


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

        //2 step. draw blue triangle
        shaderTexture2.draw(buf_big, mvp, mLightPosInEyeSpace, tex1);

        GLES20.glStencilMask(0xFF);

}

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

pic1

pic2

pic3

1 Ответ

0 голосов
/ 07 марта 2020

Учитывая указанные c операторы в порядке их выполнения ...

Следующий код установит каждый пиксель в буфере трафарета равным 1.

GLES20.glClearStencil(1);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);

Далее красный Треугольник отображается. Но функция трафарета настроена так, что каждый раз, когда тесты трафарета и глубины проходят значение 1, они записываются в буфер трафарета. Это ничего не меняет, потому что буфер трафарета уже заполнен 1.

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

// 1 step. draw red triangle
shaderTexture2.draw(buf_slim, mvp, mLightPosInEyeSpace, tex1);

На данный момент буфер трафарета все еще заполнен значением 1.

Теперь функция трафарета установка на прохождение, когда текущее значение не равно 1. Следовательно, проверка трафарета всегда будет неудачной, и фрагменты синего треугольника не будут видны.

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

// 2 step. draw blue triangle
shaderTexture2.draw(buf_big, mvp, mLightPosInEyeSpace, tex1);

Следующий код (непроверенный) изменяет такие вещи, что 0 используется в качестве значения очистки трафарета. Значение 1 записывается в те пиксели трафарета, которые покрыты красным треугольником. Наконец, синий треугольник отображается только для тех пикселей, которые имеют соответствующий пиксель трафарета, равный 1.

@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.glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GLES20.GL_REPLACE);
    GLES20.glStencilFunc(GLES20.GL_ALWAYS, 1, 0xFF);
    GLES20.glStencilMask(0xFF);

    // 1 step. draw red triangle
    shaderTexture2.draw(buf_slim, mvp, mLightPosInEyeSpace, tex1);

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

    // 2 step. draw blue triangle
    shaderTexture2.draw(buf_big, mvp, mLightPosInEyeSpace, tex1);

    GLES20.glStencilMask(0xFF);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...