趣投稿|走进 Stencil Buffer 系列 4:Stencil 后处理局部描边( 三 )
}
在 OnPreRender中我们设置了摄像机的渲染目标纹理 。
而后处理的重点在OnPostRender中 , 首先我们把Graphics的渲染激活操作目标为stencilBufferToColor , 并清除stencilBufferToColor里的颜色和深度缓冲区内容 , 并设置默认颜色为RGBA(0,0,0,0) 。 随后又设置Graphics的激活操作目标 , 写入color的目标是stencilBufferToColor.colorBuffer , 测试使用的 depth buffer 的数据来源是cameraRenderTexture.depthBuffer 。
接下来就是提取出纯颜色形式的 StencilBuffer了 , 用Blit函数将cameraRenderTexture通过StencilProcessMat模板测试材质把StencilBuffer提取出到stencilBufferToColor.colorBuffer 中 。
StencilProcessMat的作用就是对cameraRenderTexture.depthBuffer进行模板测试 Stencil Test , 如果相等才写入我们自定义的_StencilColor颜色 (白色) , 否者为RGBA(0,0,0,0) 。
StencilProcessMat的代码如下:
Shader ''Unlit/StencilProcess''
{
Properties{_MainTex (''Texture'', 2D) = ''white'' {}_StencilColor(''StencilBuffer Color'',Color)=(1,1,1,1)_RefValue(''Ref Value'',Int)=2}SubShader{Stencil{Ref [_RefValue]Comp Equal}Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include ''UnityCG.cginc''struct appdata{float4 vertex : POSITION;};struct v2f{float4 vertex : SV_POSITION;};sampler2D _MainTex;fixed4 _StencilColor;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);return o;}fixed4 frag (v2f i) : SV_Target{return _StencilColor;}ENDCG}}
}
我们在 Frame Debugger 中可以查看到这个颜色图像形式的 StencilBuffer:
本文插图
颜色图像形式的 StencilBuffer
随后就到边缘检测和原图像叠加了 , 将cameraRenderTexture通过OutlinePostProcessMat材质处理 , 并与材质中的_StencilBufferToColor进行边缘检测操作 。
//将 cameraRenderTexture 通过 OutlinePostProcessMat 材质//并与材质中的 _StencilBufferToColor 进行边缘检测操作//最后输出到 FrameBuffer( 意味着直接交付给 FramBuffer)Graphics.Blit(cameraRenderTexture, as RenderTexture,OutlinePostProcessByStencilMat);
用于边缘检测和原屏幕图像叠加的OutlinePostProcessMat材质 Shader 代码如下:
Shader ''Unlit/OutlinePostProcessByStencil''
{
Properties{_MainTex (''Texture'', 2D) = ''white'' {}_EdgeColor(''Edge Color'',Color)= (1,1,1,1)}SubShader{ZTest Always Cull Off ZWrite OffPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include ''UnityCG.cginc''struct v2f{float2 uv[9] : TEXCOORD0;float4 pos : SV_POSITION;};sampler2D _MainTex;sampler2D _StencilBufferToColor;float4 _StencilBufferToColor_TexelSize;float4 _EdgeColor;v2f vert (appdata_img v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);half2 uv = v.texcoord;o.uv[0] = uv + _StencilBufferToColor_TexelSize.xy * half2(-1, -1);o.uv[1] = uv + _StencilBufferToColor_TexelSize.xy * half2(0, -1);o.uv[2] = uv + _StencilBufferToColor_TexelSize.xy * half2(1, -1);o.uv[3] = uv + _StencilBufferToColor_TexelSize.xy * half2(-1, 0);o.uv[4] = uv + _StencilBufferToColor_TexelSize.xy * half2(0, 0);o.uv[5] = uv + _StencilBufferToColor_TexelSize.xy * half2(1, 0);o.uv[6] = uv + _StencilBufferToColor_TexelSize.xy * half2(-1, 1);o.uv[7] = uv + _StencilBufferToColor_TexelSize.xy * half2(0, 1);o.uv[8] = uv + _StencilBufferToColor_TexelSize.xy * half2(1, 1);return o;}float SobelEdge(v2f i){const half Gx[9] = {-1, 0, 1,-2, 0, 2,-1, 0, 1};const half Gy[9] = {-1, -2, -1,0, 0, 0,1, 2, 1};float edge = 0;float edgeY = 0;float edgeX = 0;float luminance =0;for(int it=0; it<9; it++){luminance = tex2D(_StencilBufferToColor,i.uv[it]).a;edgeX += luminance*Gx[it];edgeY += luminance*Gy[it];}edge = 1 - abs(edgeX) - abs(edgeY);return edge;}fixed4 frag (v2f i) : SV_Target{fixed4 sourceColor = tex2D(_MainTex, i.uv[4]);float edge = SobelEdge(i);return lerp(_EdgeColor,sourceColor,edge);}ENDCG}}
推荐阅读
- 趣投稿|工作复盘:对消息的浅析
- AI工信科创|AI技术走进西门子成都数字化工厂,释放全新潜力
- 图南指北|让Wi-Fi6走进千家万户:荣耀路由器3体验评测
- 深圳摄区|“访企业、促合作、谋发展”活动走进国家技术转移南方中心
- 兆威机电TB|微型传动系统”走进车间革命 抢抓智能制造红利
- 『』人工视觉时代,仿生眼或将问世
- 「晾霸」葵花奖走进晾霸:二十年磨一剑,专注智能电动晾衣架产品技术研发
- :人工智能开课啦!八十五中师生走进西安交叉核心院
- 趣投稿浅析机器学习中的自由度
- 趣投稿产品经理懂点技术(2):产品经理真的要懂微服务么