Не работает 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 шт):
@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 - убедитесь что трафаретный буфер вообще создан.


