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 技巧。

瀏覽並下載 完整程式碼 