news 2026/4/3 5:00:32

《Unity Shader》13.4 再谈边缘检测

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《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.cs

EdgeDetectNormalsAndDepth.cs

using 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() { GetComponent<Camera>().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.shader

Shader "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 - there's 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 }

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/21 8:08:22

JS判断左右Shift Ctrl Alt

https://blog.csdn.net/qq_46048008/article/details/126172744 https://www.w3school.com.cn/jsref/event_key_location.asp KeyboardEvent.location 0. DOM_KEY_LOCATION_STANDARD 1. DOM_KEY_LOCATION_LEFT 2. DOM_KEY_LOCATION_RIGHT 3. DOM_KEY_LOCATION_NUMPAD

作者头像 李华
网站建设 2026/3/28 9:00:40

为什么有的 Android 架构图是 4 层,有的却是 5 层?

一句话结论先给出&#xff1a; 4 层结构是早期 / 实现视角的 Android 架构图&#xff1b; 5 层结构是现代 / 工程化 / 系统级的 Android 架构认知。 两者不冲突&#xff0c;只是分层粒度和时代背景不同。 一、你可能见过的那张「4 层 Android 架构图」 很多教材、博客、老 PPT…

作者头像 李华
网站建设 2026/3/17 21:58:02

键盘按键测试

参考&#xff1a;https://www.keyboardtest.cn/ 三种布局 全键盘 隐藏数字区域 隐藏方向区域和数字区域 <html> <head> <meta name"viewport" content"widthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalableno"/> &l…

作者头像 李华
网站建设 2026/3/20 1:23:19

linux内核伙伴系统分配物理页面时水位判断zone_watermark_ok

linux内核物理页面分配函数alloc_pages(...)在进行页面分配时非常重要的一个步骤就是判断当前Zone中可用页面减去分配需求页面后的剩余可用页面和低水位值(ALLOC_WMARK_LOW)之间的关系&#xff0c;如果低于最水位值则开始直接回收,否则可以继续分配。 其中判断关键步骤由函数zo…

作者头像 李华
网站建设 2026/4/3 4:14:45

Python连接KingbaseES全指南

好的&#xff0c;这是一个使用 ksycopg2 库在 Python 中连接和操作 KingbaseES 数据库的完整指南。1. 安装依赖首先&#xff0c;确保已安装 ksycopg2 包。它是 psycopg2 的一个分支&#xff0c;专为 KingbaseES 设计。pip install ksycopg22. 建立数据库连接导入库并使用连接参…

作者头像 李华