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);
}

 

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