Как значения выводятся в буфер трафарета в этом примере? - PullRequest
0 голосов
/ 18 июня 2019

У меня серьезная проблема с пониманием того, как работает трафаретная буферизация в OpenGL.Я следовал за примерами учебника, и код, конечно, работает, но я действительно не понимаю, в какие моменты я пишу в буфер трафарета.Мне кажется, что я настраиваю трафаретные тесты, маски и все остальное, но затем я просто вызываю glDrawArrays(...) и записываю треугольники в вывод без применения буфера трафарета вообще.Я также не понимаю, почему я очищаю буфер, используя glClear(GL_STENCIL_BUFFER_BIT), прежде чем я даже рисую треугольники.Я был бы очень благодарен, если бы кто-то мог просветить меня.

// Draws the initial cube facing upwards
glDrawArrays(GL_TRIANGLES, 0, 36); 

//enable stencil testing
glEnable(GL_STENCIL_TEST);

// Draws the floor between the upward cube and downward cube 
glStencilFunc(GL_ALWAYS, 1, 0xFF); /*sets the test function, mask and ref value*/
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); /*defines what happens on restults*/
glStencilMask(0xFF); /*Mask that is applied on the bits before they are written to the stencil buffer*/
glDepthMask(GL_FALSE);
glClear(GL_STENCIL_BUFFER_BIT); /*Why do I clear the buffer here?!?*/
glDrawArrays(GL_TRIANGLES, 36, 6);

// Draws the downward cube (reflection)
glStencilFunc(GL_EQUAL, 1, 0xFF);
glDepthMask(GL_TRUE);
glStencilMask(0x00);

model = glm::scale(
glm::translate(model, glm::vec3(0, 0, -1)),
glm::vec3(1, 1, -1)
);
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));

glUniform3f(uniColor, 0.3f, 0.3f, 0.3f);
glDrawArrays(GL_TRIANGLES, 0, 36);
glUniform3f(uniColor, 1.0f, 1.0f, 1.0f);

glDisable(GL_STENCIL_TEST);

Ответы [ 2 ]

2 голосов
/ 18 июня 2019

Третье значение, переданное glStencilOp (GL_REPLACE), указывает OpenGL установить для буфера трафарета значение ref , ранее указанное в glStencilFunc, при каждом прохождении теста трафарета и теста глубины.В этом случае: 1.

Итак, вызов glDrawArrays обновляет буфер трафарета до 1 везде, где он успешно рисует (т.е. проходит оба теста).

(И причина, по которой вы его очищаетево-первых, это избавиться от любых 1, которые были там, когда вы начинали: вы не хотите, чтобы они действовали как ложные срабатывания, если вы не рисовали треугольники).

См. https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glStencilOp.xmlдля деталей.

0 голосов
/ 19 июня 2019

Хорошо, я думаю, что наконец-то понял.И просто дать ответ кому-то еще, у кого может быть тот же мышительный барьер, который был у меня здесь - вот в чем была моя проблема.В голове я подумал, что сначала нужно как-то записать значения в буфер трафарета, а потом я запишу их на дисплей.Что неправильно, как любезно сказал @NicolBolas.

Команда glDrawArrays (при активном stencilTesting) выполняет запись на дисплей, а также в буфер трафарета.Таким образом, для всего следующего мы имеем трафарет в моем примере floor в буфере и можем использовать его, чтобы оценить, будет ли нарисован пиксель.Таким образом, мы можем эффективно нарисовать второй куб только на полу, а не за его пределами.Из-за установки glStencilMask на все нули, прежде чем мы начнем рисовать куб, мы должны убедиться, что он не влияет на буфер трафарета, даже если к действию применяется тест трафарета.Если кто-то еще наткнется на это, я надеюсь, что это может помочь.И если это полная чушь, пожалуйста, кто-нибудь оставит комментарий с ошибкой в ​​моем мышлении.

...