1 边缘检测原理

​ 边缘检测的原理是:检测每个像素周围的像素亮度差,如果亮度差异较大,就将该像素识别为边缘,并进行边缘着色。

​ 本文完整资源见→Unity3D边缘检测特效

​ 使用过卷积神经网络(CNN)的人,一定知道卷积运算,笔者之前有写过相关文章(使用CNN实现MNIST数据集分类基于keras的卷积神经网络(CNN)基于keras的时域卷积网络(TCN)基于keras的胶囊网络(CapsNet)),感兴趣的读者可以了解下。

​ 周围像素的亮度差异计算,也需要使用卷积运算。对于每个像素的周围像素,我们可以给它赋予一个权值,对这些像素的亮度进行加权求和,将该加权和记作该点的一个特征值,我们可以根据该特征值决策该点是否显示为边缘色。为方便描述上述运算,我们将周围像素的权值序列记作卷积核,将加权运算记作卷积运算

​ 我们将可以描述周围像素点亮度差异的卷积核称为边缘检测算子,将使用边缘检测算子进行卷积运算得到的特征值称为梯度(记为G)。常用的边缘检测算子有 Roberts、Prewitt、Sobel,如下,它们都有两个方向上的梯度 Gx、Gy。

​ 整体梯度可以按以下公式计算得到:

​ 由于上述计算包含了开根号操作,出于性能考虑,我们使用绝对值操作代替开根号操作:

​ 得到梯度后,就可以判断哪些像素对应了边缘(梯度越大,越有可能是边缘点)。

2 代码实现

​ EdgeDetection.cs

using UnityEngine;

[RequireComponent(typeof(Camera))] // 需要相机组件
public class EdgeDetection : MonoBehaviour {
[Range(0.0f, 1.0f)]
public float edgesOnly = 0.0f; // 是否仅显示边缘
public Color edgeColor = Color.black; // 边缘颜色
public Color backgroundColor = Color.white; // 背景颜色
private Material material; // 材质 private void Start() {
material = new Material(Shader.Find("MyShader/EdgeDetect"));
material.hideFlags = HideFlags.DontSave;
} void OnRenderImage(RenderTexture src, RenderTexture dest) {
if (material != null) {
material.SetFloat("_EdgeOnly", edgesOnly);
material.SetColor("_EdgeColor", edgeColor);
material.SetColor("_BackgroundColor", backgroundColor);
Graphics.Blit(src, dest, material);
} else {
Graphics.Blit(src, dest);
}
}
}

​ EdgeDetection.shader

Shader "MyShader/EdgeDetect" {
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) // 背景颜色
} SubShader {
Pass {
// 深度测试始终通过, 关闭深度写入
ZTest Always ZWrite Off CGPROGRAM #include "UnityCG.cginc" #pragma vertex vert
#pragma fragment frag sampler2D _MainTex; // 主纹理
uniform half4 _MainTex_TexelSize; // _MainTex的像素尺寸大小, float4(1/width, 1/height, width, height)
fixed _EdgeOnly; // 是否仅显示边缘
fixed4 _EdgeColor; // 边缘颜色
fixed4 _BackgroundColor; // 背景颜色 struct v2f {
float4 pos : SV_POSITION; // 裁剪空间中顶点坐标
half2 uv[9] : TEXCOORD0; // 顶点及其周围8个点的uv坐标
}; v2f vert(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex); // 模型空间顶点坐标变换到裁剪空间, 等价于: mul(UNITY_MATRIX_MVP, v.vertex)
half2 uv = v.texcoord;
o.uv[0] = uv + _MainTex_TexelSize.xy * half2(-1, -1);
o.uv[1] = uv + _MainTex_TexelSize.xy * half2(0, -1);
o.uv[2] = uv + _MainTex_TexelSize.xy * half2(1, -1);
o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1, 0);
o.uv[4] = uv + _MainTex_TexelSize.xy * half2(0, 0);
o.uv[5] = uv + _MainTex_TexelSize.xy * half2(1, 0);
o.uv[6] = uv + _MainTex_TexelSize.xy * half2(-1, 1);
o.uv[7] = uv + _MainTex_TexelSize.xy * half2(0, 1);
o.uv[8] = uv + _MainTex_TexelSize.xy * half2(1, 1);
return o;
} fixed luminance(fixed4 color) { // 计算亮度, 以亮度作为梯度计算的参考量
return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
} half Sobel(v2f i) { // 使用Sobel边缘检测算子做卷积运算, 计算梯度
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};
half lum;
half Ex = 0;
half Ey = 0;
for (int j = 0; j < 9; j++) {
lum = luminance(tex2D(_MainTex, i.uv[j]));
Ex += lum * Gx[j];
Ey += lum * Gy[j];
}
half E = 1 - abs(Ex) - abs(Ey);
return E;
} fixed4 frag(v2f i) : SV_Target {
half edge = Sobel(i);
fixed4 withEdgeColor = lerp(_EdgeColor, tex2D(_MainTex, i.uv[4]), edge); // 边缘颜色与原图颜色插值
fixed4 onlyEdgeColor = lerp(_EdgeColor, _BackgroundColor, edge); // 边缘颜色与背景颜色插值
return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
} ENDCG
}
} FallBack Off
}

3 运行效果

1)原图

2)Edges Only 设置为 0,Edge Color 设置为绿色

3)Edges Only 设置为 1,Edge Color 设置为黑色,Background Color 设置为白色

​ 声明:本文转自【Unity3D】边缘检测特效

【Unity3D】边缘检测特效的更多相关文章

  1. Unity3d粒子特效:制作火焰效果

    效果 分析 真实的火焰效果,通常包括:火.火光.火星等组成部分,而火焰对周围环境的烘焙,可以通过灯光实现,如点光源. 针对火焰组成部分,我们可以创建对应的粒子系统组件,实现相应的效果,如下图所示: 1 ...

  2. 【Unity3D】基于粒子系统实现烟花特效

    1 需求实现 ​ 粒子系统ParticleSystem 中介绍了粒子初始化.粒子发射.发射器形状.渲染器.碰撞.子发射器.拖尾等粒子系统的基本用法,本节将基于粒子系统实现烟花特效. ​ 实现需求如下( ...

  3. Unity3D-美术相关

    1.导入动画 (1)使用预分解的动画模型,导入后面板中会含有一个可用的动画片段列表. (2)使用未分解的动画模型,自行添加动画片段. (3)使用多个动画文件,模型与动画分离.对于goober.fbx模 ...

  4. Unity塔防游戏开发

    Unity3D塔防开发流程 配置环境及场景搭建编程语言:C#,略懂些许设计模式,如果不了解设计模式,BUG More开发工具:Unity3D编辑器.Visual Studio编译器开发建议:了解Uni ...

  5. Unity3D特效-场景淡入淡出

    最近公司开始搞Unity3D..整个游戏..特效需求还是比较多的.关于UI部分的特效淡入淡出.看网上用的方法都是用个黑东东遮挡然后设置alpha这么搞....本大神感觉非常的low.而且很渣.故奋笔疾 ...

  6. unity3d 游戏插件 溶解特效插件 - Dissolve Shader

    unity3d 游戏插件 溶解特效插件 - Dissolve Shader   链接: https://pan.baidu.com/s/1hr7w39U 密码: 3ed2

  7. Unity3D之挥动武器产生的剑痕特效

    网维教程网 观看很多其它教程 眼下已知3种方法能够做这样的剑痕特效 1.尾随特效 2.程序实现动态面来处理剑痕动画. 3.美术实现剑痕动画,直接坐在模型动画里面 (由于我不会美术所以这个忽略 嘿嘿) ...

  8. [Unity3D]Unity3D游戏开发之刀光剑影特效的实现

    大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 我实在不明确有的人为什么不喜欢武侠/仙侠类游戏,也许是因为武侠/仙侠类游戏身上被永远烙上的国 ...

  9. Unity3D学习笔记——组件之Effects(效果/特效)——Particle System(粒子系统)

    Effects:效果/特效. Particle System:粒子系统.可用于创建烟雾.气流.火焰.涟漪等效果. 在Unity3D 3.5版本之后退出了新的shuriken粒子系统:   添加组件之后 ...

  10. unity3d笔记:控制特效的播放速度

           一般在游戏中,主角或者怪物会受到减速效果,或者攻击速度减慢等类似的状态.本身动作减速的同时,衔接在角色上的特效也需要改变相应的播放速度.一般特效有三个游戏组件:   关键点就是改变Ani ...

随机推荐

  1. 缓存选型:Redis or MemCache

    ★ Redis24篇集合 1 背景 互联网产品为了保证高性能和高可用性,经常会使用缓存来进行架构设计.最常用的就是使用Redis了,也有部分企业会选择使用Memcache. 所以了解 Redis 和 ...

  2. 【MicroPython】生成QSTR表 - py\makeqstrdata.py

    转义非字母数字的字符,转义结果为预定义字符串codepoint2name[] def qstr_escape(qst): def esc_char(m): c = ord(m.group(0)) tr ...

  3. [转帖]麒麟v10上部署TiDBv5.1.2生产环境的最佳实践

    https://tidb.net/book/tidb-monthly/2022/2022-07/usercase/tidb-v5-1-2 前言​ 笔者最近在一个银行项目中做 PoC 测试,由于客户选择 ...

  4. [转帖]TiKV 缩容不掉如何解决?

    TiKV节点缩容不掉,通常遇到的情况: 1.经常遇到的情况是:3个节点的tikv集群缩容肯定会一直卡着,因为没有新节点接受要下线kv的region peer. 2.另外就是除缩容tikv外,剩下的KV ...

  5. [转帖]TiKV & TiFlash 加速复杂业务查询丨TiFlash 应用实践

    返回全部 边城元元案例实践2022-08-02 复杂业务查询对于传统的关系型数据库来说是一种考验,而通过 TiKV 行存与 TiFlash 的列存结合使用就能很好地应对.本文根据 TUG 用户边城元元 ...

  6. [转帖]金仓数据库KingbaseES V8R6 索引膨胀

    索引膨胀 对于索引,随着业务不断的增删改,会造成膨胀,尤其Btree索引,也会涉及索引分裂.合并等,导致索引访问效率降低.维护成本增加.另外,索引页的复用与HEAP PAGE不一样,因为索引的内容是有 ...

  7. [转帖]安全技术和iptables防火墙

    目录 安全技术 Netfilter 防火墙工具介绍 iptables firewalld nftables iptables的组成概述 netfilter与iptables关系 iptables的四表 ...

  8. Docker镜像精简方法之二 COPY vs ADD 与镜像层

    Docker镜像精简方法之二 COPY vs ADD 与镜像层 摘要 昨天只是讲了一下大体的思路. 但是没有实操. 今天想着修改一下默认的打包镜像的命令,验证一下效果 原始命令 FROM adopto ...

  9. [转帖]Kdump调试机理详细总结(一)

    https://blog.csdn.net/luckiers/category_11796393.html 一.简介 本文主要讲解Kdump的运行机理,后续两个章节会详细介绍kdump的使用和如何分析 ...

  10. [转帖]Xargs用法详解

    https://www.cnblogs.com/cheyunhua/p/8796433.html 1. 简介 之所以能用到这个命令,关键是由于很多命令不支持|管道来传递参数,而日常工作中有有这个必要, ...