码迷,mamicode.com
首页 > 其他好文 > 详细

Stencil buffer

时间:2015-06-24 21:03:42      阅读:1461      评论:0      收藏:0      [点我收藏+]

标签:unity3d   三维图像   图形   

Stencil buffer 

模版缓冲(stencil buffer)或印模缓冲,是在OpenGL三维绘图等计算机图像硬件中常见的除颜色缓冲、像素缓冲、深度缓冲之外另一种数据缓冲。词源模版(stencil)是指一种印刷技术,通常以蜡纸或者钢板印刷文字或图形;区别于模板(template),用木板为外形修剪的依据来复制形状;模版(stencil)是指印模,而模板(template)主要是指形模。模版缓冲是以像素为单位的,整数数值的缓冲,通常给每个像素分配一个字节长度的数值。深度缓冲与模版缓冲经常在图形硬件的随机存取内存(RAM)中分享相同的区域。

模板缓冲所在的是整个流水线的最后一个阶段,这个阶段的流水线如下


技术分享



最简单的情况,模版缓冲被用于限制渲染的区域。更多高级应用会利用深度缓冲与模版缓冲的在图形渲染流水线中的强关联关系。例如,模版的数值可以按每个像素是否通过深度测试来自动增加或减少。

简单组合使用深度测试与模版修饰符可以使得大量的本来需要多次渲染过程的效果(例如阴影、外形的绘制或复合几何图元(Geometric primitive)的交叉部分的高光处理)可以简单实现,因此减轻了图形硬件的负担。

最典型的应用是给三维图像加阴影。也用于平面反射。

其它渲染的技术,例如,视口渲染(portal rendering),利用模版缓冲作其它用途。例如,它可以被用于查找被视口遮蔽的屏幕区域然后重新正确渲染这些像素点。

模版缓冲与其修饰符可以通过OpenGL或Direct3D的应用程序编程接口(API)来访问。


技术分享



常用的比较操作


 
GreaterOnly render pixels whose reference value is greater than the value in the buffer.
GEqualOnly render pixels whose reference value is greater than or equal to the value in the buffer.
LessOnly render pixels whose reference value is less than the value in the buffer.
LEqualOnly render pixels whose reference value is less than or equal to the value in the buffer.
EqualOnly render pixels whose reference value equals the value in the buffer.
NotEqualOnly render pixels whose reference value differs from the value in the buffer.
AlwaysMake the stencil test always pass.
NeverMake the stencil test always fail.

模版像素操作


 
KeepKeep the current contents of the buffer.
ZeroWrite 0 into the buffer.
ReplaceWrite the reference value into the buffer.
IncrSatIncrement the current value in the buffer. If the value is 255 already, it stays at 255.
DecrSatDecrement the current value in the buffer. If the value is 0 already, it stays at 0.
InvertNegate all the bits.
IncrWrapIncrement the current value in the buffer. If the value is 255 already, it becomes 0.
DecrWrapDecrement the current value in the buffer. If the value is 0 already, it becomes 255.


例子


下面是Unity文档里的例子,文档有点错误,按照文档的代码是写不出对应的结果的。

首先在场景里放一个红球,Shader如下
Shader "Custom/RedStencil" {

	SubShader {
		  Tags { "RenderType"="Opaque" "Queue"="Geometry"}
        Pass {
            Stencil {
                Ref 2
                Comp always
                Pass replace
                ZFail decrWrap
            }
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                float4 pos : SV_POSITION;
            };
            v2f vert(appdata v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }
            half4 frag(v2f i) : SV_Target {
                return half4(1,0,0,1);
            }
            ENDCG
        }
		}
}

结果如下

技术分享


stencil的值在球体绘制的地方被赋为2,没有绘制的地方为0.

接下来画绿色的球
Shader "Custom/GreenStencil" {
	SubShader {
 Tags { "RenderType"="Opaque" "Queue"="Geometry+1"}
        Pass {
            Stencil {
                Ref 2
                Comp equal
                Pass keep 
                Fail decrWrap 
                ZFail IncrSat
            }
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                float4 pos : SV_POSITION;
            };
            v2f vert(appdata v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }
            half4 frag(v2f i) : SV_Target {
                return half4(0,1,0,1);
            }
            ENDCG
        }
	} 
	FallBack "Diffuse"
}



绘制结果如下,绿色的部分是stencil pass的,绿球没有被绘制出来的地方stecil值会减一,变为255.

技术分享

最后画蓝色的球,shader如下
Shader "Custom/BlueStencil" {
	SubShader {
	  Tags { "RenderType"="Opaque" "Queue"="Overlay"}
        Pass {
            Stencil {
                Ref 3
                Comp Equal
            }
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                float4 pos : SV_POSITION;
            };
            v2f vert(appdata v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                return o;
            }
            half4 frag(v2f i) : SV_Target {
                return half4(0,0,1,1);
            }
            ENDCG
        }
	}
}


技术分享


蓝色球只在stencil buffer 值为3的地方绘制出来了。

参考

ShaderLab: Stencil - http://docs.unity3d.com/Manual/SL-Stencil.html
Extra buffers - https://open.gl/depthstencils
OpenGL Programming/Stencil buffer - https://en.wikibooks.org/wiki/OpenGL_Programming/Stencil_buffer

Stencil buffer

标签:unity3d   三维图像   图形   

原文地址:http://blog.csdn.net/silangquan/article/details/46608915

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!