《Unity Shader》13.4 再谈边缘检测

📅 发布时间:2026/7/5 19:05:36 👁️ 浏览次数:
《Unity Shader》13.4 再谈边缘检测
(1)(2把Scene12_6另存为 Scene_13_4(3)(4)https://github.com/candycat1992/Unity_Shaders_Book/blob/master/Assets/Scripts/Chapter13/EdgeDetectNormalsAndDepth.csEdgeDetectNormalsAndDepth.csusing UnityEngine; using System.Collections; public class EdgeDetectNormalsAndDepth : PostEffectsBase { public Shader edgeDetectShader; private Material edgeDetectMaterial null; public Material material { get { edgeDetectMaterial CheckShaderAndCreateMaterial(edgeDetectShader, edgeDetectMaterial); return edgeDetectMaterial; } } [Range(0.0f, 1.0f)] public float edgesOnly 0.0f; public Color edgeColor Color.black; public Color backgroundColor Color.white; public float sampleDistance 1.0f; public float sensitivityDepth 1.0f; public float sensitivityNormals 1.0f; void OnEnable() { GetComponentCamera().depthTextureMode | DepthTextureMode.DepthNormals; } //获取摄像机的深度法线纹理 [ImageEffectOpaque] void OnRenderImage (RenderTexture src, RenderTexture dest) { if (material ! null) { material.SetFloat(_EdgeOnly, edgesOnly); material.SetColor(_EdgeColor, edgeColor); material.SetColor(_BackgroundColor, backgroundColor); material.SetFloat(_SampleDistance, sampleDistance); material.SetVector(_Sensitivity, new Vector4(sensitivityNormals, sensitivityDepth, 0.0f, 0.0f)); Graphics.Blit(src, dest, material); } else { Graphics.Blit(src, dest); } } }Chapter13-EdgeDetectNormalAndDepth.shaderShader Custom/Chapter13-EdgeDetectNormalAndDepth { Properties { _MainTex (Base (RGB), 2D) white {} _EdgeOnly (Edge Only, Float) 1.0 _EdgeColor (Edge Color, Color) (0, 0, 0, 1) _BackgroundColor (Background Color, Color) (1, 1, 1, 1) _SampleDistance (Sample Distance, Float) 1.0 _Sensitivity (Sensitivity, Vector) (1, 1, 1, 1) //_Sensitivity的xy分量分别对应了法线和深度的检测灵敏度zw分量则没有实际用途 } SubShader { CGINCLUDE #include UnityCG.cginc sampler2D _MainTex; half4 _MainTex_TexelSize; //需要对邻域像素进行纹理采样 fixed _EdgeOnly; fixed4 _EdgeColor; fixed4 _BackgroundColor; float _SampleDistance; half4 _Sensitivity; sampler2D _CameraDepthNormalsTexture; //深度法线纹理_CameraDepthNormalsTexture struct v2f { float4 pos : SV_POSITION; half2 uv[5]: TEXCOORD0; }; v2f vert(appdata_img v) { v2f o; o.pos mul(UNITY_MATRIX_MVP, v.vertex); half2 uv v.texcoord; o.uv[0] uv; #if UNITY_UV_STARTS_AT_TOP if (_MainTex_TexelSize.y 0) uv.y 1 - uv.y; #endif o.uv[1] uv _MainTex_TexelSize.xy * half2(1,1) * _SampleDistance; o.uv[2] uv _MainTex_TexelSize.xy * half2(-1,-1) * _SampleDistance; o.uv[3] uv _MainTex_TexelSize.xy * half2(-1,1) * _SampleDistance; o.uv[4] uv _MainTex_TexelSize.xy * half2(1,-1) * _SampleDistance; return o; } //计算采样纹理坐标的代码从片元着色器中转移到顶点着色器 half CheckSame(half4 center, half4 sample) { half2 centerNormal center.xy; float centerDepth DecodeFloatRG(center.zw); half2 sampleNormal sample.xy; float sampleDepth DecodeFloatRG(sample.zw); // difference in normals // do not bother decoding normals - theres no need here half2 diffNormal abs(centerNormal - sampleNormal) * _Sensitivity.x; int isSameNormal (diffNormal.x diffNormal.y) 0.1; // difference in depth float diffDepth abs(centerDepth - sampleDepth) * _Sensitivity.y; // scale the required threshold by the distance int isSameDepth diffDepth 0.1 * centerDepth; // return: // 1 - if normals and depth are similar enough // 0 - otherwise return isSameNormal * isSameDepth ? 1.0 : 0.0; } fixed4 fragRobertsCrossDepthAndNormal(v2f i) : SV_Target { half4 sample1 tex2D(_CameraDepthNormalsTexture, i.uv[1]); half4 sample2 tex2D(_CameraDepthNormalsTexture, i.uv[2]); half4 sample3 tex2D(_CameraDepthNormalsTexture, i.uv[3]); half4 sample4 tex2D(_CameraDepthNormalsTexture, i.uv[4]); half edge 1.0; edge * CheckSame(sample1, sample2); edge * CheckSame(sample3, sample4); fixed4 withEdgeColor lerp(_EdgeColor, tex2D(_MainTex, i.uv[0]), edge); fixed4 onlyEdgeColor lerp(_EdgeColor, _BackgroundColor, edge); return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly); }//采样点的对应值相减并取绝对值再乘以灵敏度参数把差异值的每个分量相加再和一个阈值比较如果它们的和小于阈值则返回1说明差异不明显不存在一条边界否则返回0。最后我们把法线和深度的检查结果相乘作为组合后的返回值 ENDCG Pass { ZTest Always Cull Off ZWrite Off CGPROGRAM #pragma vertex vert #pragma fragment fragRobertsCrossDepthAndNormal ENDCG } } FallBack Off }