Я пытаюсь добиться следующего эффекта в OpenGL, как показано в данной ссылке http://commons.wikimedia.org/wiki/File:OpenGL_Tutorial_Stencil.png, ниже также приведен фрагмент кода, это официальное руководство по openGL wikipedia.
Несмотря на то, что он содержит код и комментирует объяснения, мне все еще трудно понять логику работы буфера трафарета в openGL. Напоминаю, что перед тем, как приступить к трафарету, я прочитал большинство инструкций из красной книги, так что я знаю и знаю, как работает glStencilFunc, glStencilOp, glStencilMask и т. Д., Но все еще есть некоторые неясные и неясные вещи в мой разум связан с трафаретом.
Вот мое пошаговое руководство по интерпретации кода:
С glStencilFunc(GL_NEVER, 1, 0xFF); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
Я считаю, что тестирование по трафарету всегда будет проходить, и провал теста по трафарету приведет к заполнению 1 с в буфере трафарета из-за инструкций, установленных в glStencilOp
Если предыдущие кодовые блоки (# 1) устанавливают все пиксели в буфере трафарета, чего мы достигаем glStencilMask(0xFF);
вызов процедуры. Гарантируем ли мы, что все 1 успешно записаны в буфер трафарета или что на самом деле?
Рисуем круг, затем включаем маски, но на этот раз glStencilMask(0x00)
Вот одна из путаниц, я думаю, что это связано с предотвращением переопределения значений буфера трафарета новыми значениями, но комментарии кода говорят, что это просто заполняет буфер трафарета нулями.
Наконец, если вы не измените какое-либо значение (из-за glStencilMask(0x00)
) в буфере трафарета, какой смысл иметь
// fill 0s
glStencilFunc(GL_EQUAL, 0, 0xFF);
/* (nothing to draw) */
// fill 1s
glStencilFunc(GL_EQUAL, 1, 0xFF);
Основное тело программы:
void onDisplay() {
glClearColor(0.1, 0.1, 0.1, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glStencilFunc(GL_NEVER, 1, 0xFF);
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); // draw 1s on test fail (always)
// draw stencil pattern
glStencilMask(0xFF);
glClear(GL_STENCIL_BUFFER_BIT); // needs mask=0xFF
draw_circle();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
glStencilMask(0x00);
// fill 0s
glStencilFunc(GL_EQUAL, 0, 0xFF);
/* (nothing to draw) */
// fill 1s
glStencilFunc(GL_EQUAL, 1, 0xFF);
draw_scene();
glDisable(GL_STENCIL_TEST);
glutSwapBuffers();
}
glStencilMask(0xFF)
аналогично glColorMask(true, true, true, true)
или же glDepthMask(true)
functions — 0xFF — это маска, которая побитовая И применяется к любым трафаретным данным перед их записью в буфер трафарета. Поэтому через glStencilMask(0xFF)
мы гарантируем, что любое значение, которое OpenGL пытается записать в буфер трафарета, будет успешно записано.
glStencilMask(0x00)
: когда 0x00 побитовое И с любым байтом, выход всегда будет равен 0. Таким образом, каждый раз, когда будут пытаться записать байты в буфер трафарета, записанный байт будет равен 0. По сути, на этом этапе он просто гарантирует, что в буфере трафарета НЕ записаны новые данные.
Согласно моей интерпретации, раздел с /* (nothing to draw) */
комментарий, где вы будете рисовать материалы, предназначенные для вне трафарета проверен круг. 0 — это значение по умолчанию в буфере трафарета; поэтому, поскольку область в круге помечена как 1, пиксели, которые находятся за пределами круга, пройдут, а пиксели внутри будут отброшены. Это просто заполнитель.
Я считаю, что когда в комментариях говорится // fill 0s
, что они имеют в виду, что «все, что нарисовано здесь, заполнит часть буфера трафарета это установлено в 0. Учитывая призыв к glStencilFunc
с GL_EQUAL
а также 0
в качестве аргументов, это то, что произойдет. Я также уверен, что когда в комментариях говорится // fill 1s
они означают то же самое, но с частью буфера трафарета, установленной в 1 (то есть область, где круг был нарисован в буфере трафарета).
Других решений пока нет …