6 Introduce stencil buffer

模板測試:

模板測試最經典的用途是,將屏幕上不規則的區域屏蔽掉,防止在該區域中繪圖。比如需要在場景中繪製一面鏡子及它反射的物體。即可以繪製鏡子以形成模板緩存,然後繪製場景中的物體,只有可以通過模板測試(也即是在鏡子中)的東西纔會繪製出來。


流程如下: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);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章