当前位置: 首页 > news >正文

《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 }

http://www.jsqmd.com/news/319140/

相关文章:

  • 灵衢互联社区筹备工作会议顺利召开,多方聚力共建繁荣生态
  • 用Ollama Launch连接AI编码代理
  • 2025新质生产力示范案例发布,华为云CloudMatrix AI Infra荣获人工智能TOP案例
  • WindowServer 2016激活
  • Clawdbot+Ollama:真正隐私
  • 动态SQL实现模糊查询
  • Arch Linux上使用VSCode + STM32CubeMX + stlink + CMake + Cortex-Debug + gcc配置stm32开发环境
  • 从龟速到光速:SQL优化与索引的实战心法
  • Java计算机毕设之基于springboo的小区车辆管理系统车位信息、临时车辆信息、IC卡管理(完整前后端代码+说明文档+LW,调试定制等)
  • Java计算机毕设之基于springboo的大学生社团活动平台基于springboo+vue的学生活动组织管理系统(完整前后端代码+说明文档+LW,调试定制等)
  • libmodbus 源码分析(发送请求篇)
  • 【毕业设计】基于springboo的大学生社团活动平台(源码+文档+远程调试,全bao定制等)
  • 小程序计算机毕设之基于springboot的4S店试驾平台小程序汽车销售系统(完整前后端代码+说明文档+LW,调试定制等)
  • 从零基础到精通漏洞挖掘,流程指南超详整理,这一篇收藏就够用
  • 补剂 男性 维生素
  • 【毕业设计】基于springboot的4S店试驾平台小程序(源码+文档+远程调试,全bao定制等)
  • JS判断左右Shift Ctrl Alt
  • 为什么有的 Android 架构图是 4 层,有的却是 5 层?
  • React19 渲染流程
  • GIT中分支合并的方法
  • 作为AI应用架构师,我每天都在用的8个核心技能
  • Gemini3ProImage(nano banana 2 )异步调用接口(API)生成图片
  • P1114 “非常男女”计划
  • 键盘按键测试
  • 在计算属性中获取 Vuex 状态是标准做法(附:Vue 3 计算属性详解及和 watch 对比)
  • VSCode如何使用claude code(VS Code + Claude API 详细教程)(API 配置图文全攻略)
  • 深度学习篇--- transform(转换器)
  • 【双端队列bfs】
  • 算法入门打卡Day2___滑动窗口法、螺旋矩阵、前缀和(区间和问题,开发商购买土地问题)、数组与容器的区别
  • 【Vue知识点总结】Vue 路由中的 hidden: true:路由控制技巧