除了深度測試,opengl還有一種較為自由的測試,稱為模板測試stencil。
首先,和深度測試一樣,我們要先啟用它,同時需要在渲染迴圈中清除它的快取
glenable(gl_stencil_test);
glclear(gl_color_buffer_bit | gl_depth_buffer_bit | gl_stencil_buffer_bit);
除此以外,我們還可以使用以下函式開啟和禁用模板值的寫入
glstencilmask(0xff); // 每一位寫入模板緩衝時都保持原樣
glstencilmask(0x00); // 每一位在寫入模板緩衝時都會變成0(禁用寫入)
深度測試預設取深度淺的,因為這符合我們的常識。模板測試中,哪些值能通過,必須通過函式設定好。
舉例如下,第乙個引數是測試模式,可用的選項有:gl_never、gl_less、gl_lequal、gl_greater、gl_gequal、gl_equal、gl_notequal和gl_always。它們的語義和深度緩衝的函式類似。
第二個引數是參考值。用來進行對比。
第三個引數是乙個掩碼,它將會與參考值和儲存的模板值在測試比較它們之前進行與(and)運算。初始情況下所有位都為1。
glstencilfunc(gl_equal, 1, 0xff)
以上這個函式的意義就是告訴opengl,只要乙個片段的模板值等於(gl_equal)參考值1,片段將會通過測試並被繪製,否則會被丟棄。
除了怎麼測試,我們還要設定如何更改模板的值
glstencilop(glenum sfail, glenum dpfail, glenum ***ass)
它的三個引數含義如下
sfail:模板測試失敗時採取的行為。
dpfail:模板測試通過,但深度測試失敗時採取的行為。
***ass:模板測試和深度測試都通過時採取的行為。
每個引數都可以設定為以下的任意乙個:
gl_keep 保持當前儲存的模板值
gl_zero 將模板值設定為0
gl_replace 將模板值設定為glstencilfunc函式設定的ref值
gl_incr 如果模板值小於最大值則將模板值加1
gl_incr_wrap 與gl_incr一樣,但如果模板值超過了最大值則歸零
gl_decr 如果模板值大於最小值則將模板值減1
gl_decr_wrap 與gl_decr一樣,但如果模板值小於0則將其設定為最大值
gl_invert 按位翻轉當前的模板緩衝值
我們可以用它來做乙個物體邊框的效果
具體步驟如下:
下面是主體**
shader.use();
glm::mat4 model(1.0f);
shader.setmat4("model", model);
glm::mat4 view = camera.getviewmatrix();
shader.setmat4("view", view);
glm::mat4 projection = glm::perspective(glm::radians(45.0f), 1920.0f / 1080.0f, 0.1f, 100.0f);
shader.setmat4("projection", projection);
glstencilmask(0x00);
glbindvertexarray(planevao);
glbindtexture(gl_texture_2d, planetexture);
gldrawarrays(gl_********s, 0, 6);
glbindvertexarray(0);//地面繪製
glstencilfunc(gl_always, 1, 0xff);
glstencilmask(0xff);
glbindvertexarray(cubevao);
glbindtexture(gl_texture_2d, cubetexture);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
shader.setmat4("model", model);
gldrawarrays(gl_********s, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0f));
shader.setmat4("model", model);
gldrawarrays(gl_********s, 0, 36);
glbindvertexarray(0);//箱子繪製
frameshader.use();
frameshader.setmat4("view", view);
frameshader.setmat4("projection", projection);
glstencilfunc(gl_notequal, 1, 0xff);
glstencilmask(0x00);
gldisable(gl_depth_test);
glbindvertexarray(cubevao);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
model = glm::scale(model, glm::vec3(1.05f, 1.05f, 1.05f));
frameshader.setmat4("model", model);
gldrawarrays(gl_********s, 0, 36);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0f));
model = glm::scale(model, glm::vec3(1.05f, 1.05f, 1.05f));
frameshader.setmat4("model", model);
gldrawarrays(gl_********s, 0, 36);
glbindvertexarray(0);
glstencilmask(0xff);
glstencilfunc(gl_always, 0, 0xff);
glenable(gl_depth_test);
注意: Learn高階OpenGL筆記10模板測試
片段著色器處理完乙個片段後,模板測試會執行,和深度測試一樣,可能會丟棄片段。被保留的片段進入深度測試,會丟棄更多的片段,模板測試是根據又乙個緩衝來進行的,叫做模板緩衝。乙個模板緩衝中,每個模板值是8位的,可以將這些模板值設定為我們想要的值,然後當某乙個片段有某乙個模板值的時候,我們就可以選擇丟棄或是...
USACO4 2 網路流模板題
裸的網路流 練習抄模板 紅書dinic 因為bool寫成int除錯了好久qaq 繼續抄模板 匈牙利演算法 vector g maxn 與i相關聯 int from maxn tot bool use maxn bool match int x return false int hungary 嘗試每...
OpenGL學習二十九 模板緩衝區與模板測試
幀緩衝區有許多緩衝區構成,這些緩衝區大致分為 顏色緩衝區 用於繪圖的緩衝區,它包含了顏色索引或者rgba顏色資料。深度緩衝區 儲存每個畫素的深度值,當啟動深度測試時,片段畫素深度值和深度緩衝區深度值進行比較,決定片段哪些畫素點資料可以替換到顏色緩衝區中。模板緩衝區 就像使用紙板和噴漆一樣精確的混圖一...