OpenGL 编程/迷你门户递归
外观
绘制门户内的门户引入了一套新的极端情况。
以下是算法概述
/* TODO: Code here */
模板缓冲区将逐步创建
- 绘制门户形状
- 绘制其与子门户形状的交集以获得新的门户剪切形状
- 重复
获得交集并不简单
- 使用 GL_INCR 绘制外部门户
- 使用 GL_INCR 绘制子门户
- 使用 GL_DECR 重新绘制外部门户
- 像素>=1 代表外部门户和子门户之间的交集
从技术上讲,我们可以在每个递归级别保存和恢复缓冲区(而不是从头开始重新绘制所有门户形状),但这会很慢,并且使用 OpenGL ES 2 无法检索模板缓冲区数据。
外部门户和子门户完全是同一个对象,只有视图矩阵会改变。因此,我们向函数传递一个视图堆栈,并在每个新的递归级别推送一个新的视图矩阵。
请注意,模板绘制必须支持体积门户,这意味着它可能会被写入多次(因此您无法仅使用 GL_INVERT 实现交集)。
void draw_portal_stencil(vector<glm::mat4> view_stack, Mesh* portal) {
GLboolean save_color_mask[4];
GLboolean save_depth_mask;
glGetBooleanv(GL_COLOR_WRITEMASK, save_color_mask);
glGetBooleanv(GL_DEPTH_WRITEMASK, &save_depth_mask);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glStencilFunc(GL_NEVER, 0, 0xFF);
glStencilOp(GL_INCR, GL_KEEP, GL_KEEP); // draw 1s on test fail (always)
// draw stencil pattern
glClear(GL_STENCIL_BUFFER_BIT); // needs mask=0xFF
glUniformMatrix4fv(uniform_v, 1, GL_FALSE, glm::value_ptr(view_stack[0]));
portal->draw();
for (unsigned int i = 1; i < view_stack.size() - 1; i++) { // -1 to ignore last view
// Increment intersection for current portal
glStencilFunc(GL_EQUAL, 0, 0xFF);
glStencilOp(GL_INCR, GL_KEEP, GL_KEEP); // draw 1s on test fail (always)
glUniformMatrix4fv(uniform_v, 1, GL_FALSE, glm::value_ptr(view_stack[i]));
portal->draw();
// Decremental outer portal -> only sub-portal intersection remains
glStencilFunc(GL_NEVER, 0, 0xFF);
glStencilOp(GL_DECR, GL_KEEP, GL_KEEP); // draw 1s on test fail (always)
glUniformMatrix4fv(uniform_v, 1, GL_FALSE, glm::value_ptr(view_stack[i-1]));
portal->draw();
}
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
/* Fill 1 or more */
glStencilFunc(GL_LEQUAL, 1, 0xFF);
glColorMask(save_color_mask[0], save_color_mask[1], save_color_mask[2], save_color_mask[3]);
glDepthMask(save_depth_mask);
glUniformMatrix4fv(uniform_v, 1, GL_FALSE, glm::value_ptr(view_stack.back()));
// -Ready to draw main scene-
}
如果您需要调试并查看形状的外观,请考虑使用 fill_screen 技巧。
浏览并下载 完整代码