[Unity Shader 技术整理]边缘检测的使用(一)
来源:互联网 发布:js代码调用 编辑:程序博客网 时间:2024/05/18 03:10
先上一张Gif效果图,屋里的衣柜来一张~
用到的 : 边缘检测Shader + UV移动 + 渐变图遮罩 + 双Pass + EasyAR
完整代码 :
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_MaskTex("MaskTex", 2D) = "white" {}
_EdgeOnly ("Edge Only", Float) = 1.0
_EdgeColor ("Edgge Color", Color) = (0,0,0,1)
_BackgroundColor ("Background Color",Color) = (1,1,1,0)
_Thickness ("Thickness",Float) = 1.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
cull off
LOD 100
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 maskuv : TEXCOORD0;
float2 uv[9] : TEXCOORD1;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
sampler2D _MaskTex;
float4 _MainTex_TexelSize;
fixed _EdgeOnly;
fixed4 _EdgeColor;
fixed4 _BackgroundColor;
fixed _Thickness;
fixed luminance(fixed4 color)
{
return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
}
half Sobel(v2f i)
{
const half Gx[9] = {-1,-2,-1,0,0,0,1,2,1};
const half Gy[9] = { -1,0,1,-2,0,2,-1,0,1 };
half texColor;
half edgeX = 0;
half edgeY = 0;
for (int it = 0; it < 9; it++)
{
texColor = luminance(tex2D(_MainTex, i.uv[it]));
edgeX += texColor * Gx[it];
edgeY += texColor * Gy[it];
}
half edge = 1 - abs(edgeX) - abs(edgeY);
return edge;
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
half2 uv = v.uv;
o.maskuv = v.uv + frac(fixed2(0,-0.7 * _Time.y));
o.uv[0] = uv + _MainTex_TexelSize.xy * half2(-1, -1) * _Thickness;
o.uv[1] = uv + _MainTex_TexelSize.xy * half2(0, -1)* _Thickness;
o.uv[2] = uv + _MainTex_TexelSize.xy * half2(1, -1)* _Thickness;
o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1, 0)* _Thickness;
o.uv[4] = uv + _MainTex_TexelSize.xy * half2(0, 0)* _Thickness;
o.uv[5] = uv + _MainTex_TexelSize.xy * half2(1, 0)* _Thickness;
o.uv[6] = uv + _MainTex_TexelSize.xy * half2(-1, 1)* _Thickness;
o.uv[7] = uv + _MainTex_TexelSize.xy * half2(0, 1)* _Thickness;
o.uv[8] = uv + _MainTex_TexelSize.xy * half2(1, 1)* _Thickness;
//o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
half edge = Sobel(i);
fixed4 maskColor = tex2D(_MaskTex, i.maskuv);
fixed4 withEdgeColor = lerp(_EdgeColor,tex2D(_MainTex, i.uv[4]),edge);
fixed4 onlyEdgeColor = lerp(_EdgeColor, _BackgroundColor, edge);
fixed4 col = lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
return fixed4(col.rgb,col.a * (1.0 - maskColor.r));
}
ENDCG
}
}
}
然后开始对冯乐乐同学的源码进行加工...
第一步 :Blend SrcAlpha OneMinusSrcAlpha 开启混合,目的只是为了让背景色可以透明,只保留边缘线的颜色
第二步 :用绘图软件搞一个扫描线遮罩图,用作和边缘线遮罩,让边缘线只在黑色区域可见,图如下
第三步 :让UV动起来,也就是代码中的 maskuv,代码如下
o.maskuv = v.uv + frac(fixed2(0,-0.7 * _Time.y));
将maskuv.y的值沿着y轴向下移,_Time是内置变量,有四个分量,xyzw,他们之间存在一个倍率关系,这里用的是y。
maskuv是作为扫描线颜色的依据,代码如下
fixed4 maskColor = tex2D(_MaskTex, i.maskuv);
至此,就会得到一个黑色扫描线不断向下移动的扫描线遮罩图
第五步 :扫描线遮罩图的灰度和边缘线本身的透明度相乘,因为黑色是0 0 0,白色是1 1 1,而我需要的是黑色地方扫描线显示
假设边缘线的透明度为a,扫描线遮罩图输出的颜色为c,则最终的透明度应该是a(1-c.r),这里用的是r分量,其实gb分量也无所谓,反正是黑白的,三个值都是一样的,代码如下
fixed4(col.rgb,col.a * (1.0 - maskColor.r));
col是冯乐乐同学输出的结果,透明度由输出的结果和遮罩共同控制。
第六步 :添加一个_Thinkness参数,作为扫描线的宽度,就是为了美观考虑吧,没啥太大用处,觉得太细可以把值调大点,另外可以随着uv偏移修改颜色,输出一条五彩缤纷的扫描线,反正我懒得做....
第七步 : 去EasyAR官网弄个包,弄个Key,把prefab拖进来,Key粘进去,删除原来的摄像机,blabla...把带有上面Shader的Material拖入到RealityPlane里面,完工
- [Unity Shader 技术整理]边缘检测的使用(一)
- unity 边缘检测shader简介(一)
- unity shader-边缘检测
- unity 边缘检测shader简介(二)
- unity shader-边缘发光
- Unity Shader 学习笔记(20) 卷积、卷积核、边缘检测算子、边缘检测
- Shader实例 : 边缘检测
- Unity Shader 表面着色器边缘光(Rim Lighting)一
- 【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态
- Unity ShaderLab(二) 支持透明的边缘发光Shader
- Shader特效——“Canny边缘检测”的实现 【GLSL】
- Unity Shader 学习笔记(26) 边缘检测(深度和法线纹理)
- 边缘检测技术传统的概述
- 基于C++的图像边缘检测技术
- Unity的Shader开发教程整理
- 数字图像的边缘检测(一)
- Unity|ShaderLab笔记整理-一(Shader组成)
- unity的图像边缘检测以及简单的模糊效果
- 线程基础1
- hadoop配置遇到的问题(更新中)
- 不同 数据类型对toString()方法的使用
- 乐观锁和悲观锁定义
- Codeforces Round #387 (Div. 2) B. Mammoth's Genome Decoding
- [Unity Shader 技术整理]边缘检测的使用(一)
- POJ 1861 Network(最小生成树+克鲁斯卡尔)
- 最基础的动态规划(1)——POJ 3176 POJ 1163 相同的题
- 2.分布式文件系统HDFS之一
- android画空心圆
- VGGNet
- mfs监控
- 单链表判环判相交综合题
- ButterKnife8.8注入框架+Android ButterKnife Zelezny插件组合