模板缓冲在传统的DirectX中,广泛使用在镜面反射,遮罩,投影等效果.
在stage3d中同样可以使用,而且API被极大的整合了.
DirectX中的API:略
模板缓冲的区域就是用户的屏幕大小,它可以用来做一些检测,然后设置像素的填充方式.
简单说来,当缓冲为空时,我们可以让程序做一些事情,当缓冲被填满时,我们可以做另一些事情.做完后,考虑清空缓冲.
以龙书中镜面效果来说
我们先设置模板缓冲为空.
然后我们在屏幕上画一面镜子,镜子的像素将被绘制到缓冲中.
我们在镜子的表面画一个茶壶,茶壶的投影仅在缓冲区中有镜子的像素的位置进行替换.
最后清空缓冲.
当然,在绘制中还有很多注意事项的,比如为了让茶壶紧贴镜子,必须关闭深度缓冲.待投影绘制完毕后,开启深度缓冲.
下面是一个简单的demo.
先开启模板缓冲,当绘制三角形后,缓冲在有像素的地方从0递增到1
我们先绘制一个矩形,并随便贴一张图.
在值为1的缓冲区域绘制一个三角形.
结果就是,三角形仅在有矩形的区域内被绘制了.
地址如下:http://www.dreamfairy.cn/blog/work/flash/3d/stage3dStencilTest/StencilTest0.html
完全的镜面效果,就下篇文章再发了,也许明天心情好的话~
主要代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | private function renderScene() : void { m_context.setDepthTest(false,Context3DCompareMode.LESS); m_context.setStencilReferenceValue(0); m_context.setStencilActions(Context3DTriangleFace.FRONT_AND_BACK, Context3DCompareMode.EQUAL, Context3DStencilAction.INCREMENT_SATURATE); drawCube(); m_context.setStencilReferenceValue(1); drawTriangle(); } private function drawTriangle() : void { m_modelMatrix.identity(); m_finalMatrix.identity(); m_finalMatrix.append(m_modelMatrix); m_finalMatrix.append(m_viewMatrix); m_finalMatrix.append(m_projMatrix); m_context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,m_finalMatrix,true); m_context.setProgram(m_shader); m_context.setTextureAt(0,null); m_context.setVertexBufferAt(0, m_triangleVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); m_context.setVertexBufferAt(1,null); m_context.drawTriangles(m_triangleIndexBuffer,0,1); } private var t : Number = 0.0; private function drawCube() : void { t += .1; m_modelMatrix.identity(); m_modelMatrix.appendTranslation(Math.sin(t),0,0); m_finalMatrix.identity(); m_finalMatrix.append(m_modelMatrix); m_finalMatrix.append(m_viewMatrix); m_finalMatrix.append(m_projMatrix); m_context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,m_finalMatrix,true); m_context.setProgram(m_textureShader); m_context.setTextureAt(0,texture); m_context.setVertexBufferAt(0, m_rectVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); m_context.setVertexBufferAt(1,m_rectVertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); m_context.drawTriangles(m_rectIndexBuffer,0,2); } |