learnOpenGL 4 2 模板測試

2021-10-09 18:22:29 字數 3349 閱讀 3073

除了深度測試,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顏色資料。深度緩衝區 儲存每個畫素的深度值,當啟動深度測試時,片段畫素深度值和深度緩衝區深度值進行比較,決定片段哪些畫素點資料可以替換到顏色緩衝區中。模板緩衝區 就像使用紙板和噴漆一樣精確的混圖一...