news 2026/3/26 7:48:59

《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/24 2:25:39

从零基础到精通漏洞挖掘,流程指南超详整理,这一篇收藏就够用

一、漏洞与Bug 漏洞&#xff1a;通常情况下不影响软件的正常功能&#xff0c;但如果被攻击者利用&#xff0c;有可能驱使软件去执行一些额外的恶意代码&#xff0c;从而引发严重的后果。最常见的漏洞有缓冲区溢出漏洞、整数溢出漏洞、指针覆盖漏洞等。 Bug&#xff1a;影响软…

作者头像 李华
网站建设 2026/3/21 11:50:04

深度学习篇--- transform(转换器)

1. 核心比喻&#xff1a;厨房烹饪流水线 想象你是一个厨师&#xff0c;要做一道菜&#xff08;比如炒菜&#xff09;。原始食材&#xff08;数据&#xff09;不能直接下锅&#xff0c;需要预处理&#xff1a; 生蔬菜&#xff08;原始数据&#xff09; → 清洗&#xff08;Sta…

作者头像 李华
网站建设 2026/3/14 8:56:56

nacos作为dubbo服务注册中心

nacos作为dubbo注册中心&#xff0c;代码里也配置了nacos集群地址&#xff1b;但发现运维重启1个节点&#xff0c;会导致应用还是找不到对应的dubbo服务。这是为什么&#xff1f;java应用报错如下&#xff1a;No provider available from registry 192.168.173.154:8848,192.16…

作者头像 李华
网站建设 2026/3/25 1:28:39

Nginx基础

Nginx 基础文档 一、Nginx 配置文件结构概述 Nginx 的主配置文件通常位于&#xff1a; Linux: /etc/nginx/nginx.confmacOS (Homebrew): /usr/local/etc/nginx/nginx.confWindows: nginx/conf/nginx.conf 配置文件采用分层块结构&#xff0c;主要由以下几部分组成&#xff…

作者头像 李华
网站建设 2026/3/26 0:29:07

从 JSON Schema 到企业级动态数据模型:动态表单的终极演进路线

从 JSON Schema 到企业级动态数据模型:动态表单的终极演进路线 在很多团队里,“动态表单”往往被理解为: 前端根据一份 JSON 配置渲染表单,避免写死页面。 但真正有价值的动态表单系统,从来不只是 UI 技术,而是一个 以 Schema 为核心的企业级动态数据模型平台。 它让数据…

作者头像 李华