模板測試:
模板測試最經典的用途是,將屏幕上不規則的區域屏蔽掉,防止在該區域中繪圖。比如需要在場景中繪製一面鏡子及它反射的物體。即可以繪製鏡子以形成模板緩存,然後繪製場景中的物體,只有可以通過模板測試(也即是在鏡子中)的東西纔會繪製出來。
流程如下:http://www.cppblog.com/lovedday/archive/2008/03/19/44875.html
1、正常渲染所有的場景——地板,牆,鏡子和茶壺——不包含反射的茶壺。注意這一步沒有修改模板緩存。
2、清除模板緩存爲0。圖8.3顯示了後臺緩存和模板緩存。
3、渲染只有鏡子部分的圖元到模板緩存中。設置模板測試總是成功,並且假如測試成功就指定模板緩存入口爲1。我們僅僅渲染鏡子,在模板緩存中的所有像素都將爲0,除了鏡子部分爲1以外。圖8.4顯示了更新以後的模板緩存。也就是說,我們在模板緩存中對鏡子像素做了標記。
4、現在我們渲染被反射的茶壺到後臺緩存和模板緩存中。但是假如模板測試通過,我們就只渲染後臺緩存。假如在模板緩存中的值爲1,那麼我們設置模板測試通過。這樣,茶壺就僅僅被渲染到模板緩存爲1的地方了。因爲只有鏡子對應的模板緩存值爲1,所以反射的茶壺就只能被渲染到鏡子裏。
下面這個例子:
先畫圓柱體外面的球,然後通過“畫”圓柱體來生成模板,再繪製球(只有通過前面生成的模板的測試能被畫出來,並且這次選擇顯示球的內表面。),再畫了兩次圓柱體(這次是真正的畫,而且要畫兩次是由於半透的原因,要畫一次正面一次反面)。
OpenGL ES 示例代碼:
RenderLoop:
{
// Clear the color, depth and stencil buffers
// 清空一些buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// render Sphere outside the stencil volume
// 畫球
m_Sphere.DrawMesh(0);
// only the stencil test and depth test pass will mark the stencilbuffer value !0.
// 得到模板緩存,只有嵌入到圓柱體的部分才被標記
glEnable(GL_STENCIL_TEST);
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glDepthMask(GL_FALSE);
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
glUniformMatrix4fv(m_ShaderProgram.auiLoc[eMVPMatrix], 1, GL_FALSE, mCylinder.ptr());
m_Cylinder.DrawMesh(0);
// render the sphere again, only the pixel inside the stencil volume will been draw
// 畫球,只有在圓柱體內部分纔會被顯示
glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
m_Sphere.DrawMesh(0);
// Draw back faces of the cylinder
// 繪製圓柱體
glCullFace(GL_FRONT);
m_Cylinder.DrawMesh(0);
// Draw the front faces
glCullFace(GL_BACK);
m_Cylinder.DrawMesh(0);
}