如果只是區分的話,簡單的方法就是相機前加一個灰色quad,如下圖,但明顯不如灰化對比度高
下面就來實現這個功能
首先,我們要建一個屏幕特效腳本掛在到相機上
01
02
03
04
05
06
07
08
09
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
|
using
System; using
UnityEngine; namespace
UnityStandardAssets.ImageEffects {
[ExecuteInEditMode]
[RequireComponent
( typeof (Camera))]
public
class
GrayEffect : PostEffectsBase {
public
Shader TintShader = null ;
public
Color TintColour; public
Material TintMaterial = null ;
public
override
bool
CheckResources () {
CheckSupport
( true );
TintMaterial
= CheckShaderAndCreateMaterial (TintShader,TintMaterial); if
(!isSupported) ReportAutoDisable
(); return
isSupported; }
public
void
SetVector(Vector3 left,Vector3 right) { TintMaterial.SetVector
( "_Line" , new
Vector4(left.x,left.y,right.x,right.y)); } public
void
SetAB( float
a, float
b, float
hasA) { TintMaterial.SetVector
( "_ab" , new
Vector3(a,b,hasA)); } void
OnRenderImage (RenderTexture source, RenderTexture destination) {
if
(CheckResources()== false )
{
Graphics.Blit
(source, destination); return ;
}
TintMaterial.SetColor( "TintColour" ,
TintColour); //Do
a full screen pass using TintMaterial Graphics.Blit
(source, destination, TintMaterial); }
}
} |
Graphics.Blit 位塊傳送,拷貝源紋理到目的渲染紋理。可簡單理解爲獲取該相機的rendertexture作爲紋理,通過指定shader再渲染一遍
setvector函數用作將橫線上兩點座標傳入材質
setab即爲將y=ax+b形式的a,b傳入,並指明a是否有意義,因爲當直線形式爲x=某數字時,a無意義
具體計算如下
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
void
Calculate() { wpLeft
= portTrans.TransformPoint ( new
Vector3 (-10f, 0f, 0f)); //porttrans爲橫線中心trans wpRight
= portTrans.TransformPoint ( new
Vector3 (10f, 0f, 0f)); vpLeft
= mainCamera.WorldToViewportPoint (wpLeft); vpRight
= mainCamera.WorldToViewportPoint (wpRight); if
(vpLeft.x != vpRight.x) { va
= (vpRight.y - vpLeft.y) / (vpRight.x - vpLeft.x); vb
= vpLeft.y - vpLeft.x * va; wb
= wpLeft.y - wpLeft.x * va; hasA
= 1f; }
else
{ va
= vb = hasA = 0f; } } void
SetMaterial() { grayEffect.SetVector
(vpLeft, vpRight); grayEffect.SetAB
(va,vb,hasA); } |
01
02
03
04
05
06
07
08
09
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
|
Shader
"Custom/Tint" {
Properties
{
_MainTex
( "" ,
any) = ""
{} _Line
( "line" ,
Vector) = (0,0,0,0) _ab
( "ab" ,
Vector) = (0,0,0) }
CGINCLUDE
#include
"UnityCG.cginc" struct
v2f {
float4
pos : SV_POSITION; float3
wPos : TEXCOORD1; float2
uv : TEXCOORD0; };
sampler2D
_MainTex; float4
_Line; float3
_ab; float4
TintColour; v2f
vert( appdata_img v ) {
v2f
o = (v2f)0; o.pos
= mul(UNITY_MATRIX_MVP, v.vertex); o.wPos
= v.vertex; o.uv
= v.texcoord; return
o; }
float4
frag(v2f input) : SV_Target {
float4
c = tex2D(_MainTex, input.uv); bool
isGray = false ; if (_ab.z==0) { if (_Line.y>_Line.w&&input.wPos.x>_Line.x) { isGray
= true ; } if (_Line.y<_Line.w&&input.wPos.x<_Line.x) { isGray
= true ; } } else { float
ey = _ab.x*input.wPos.x + _ab.y; if (_Line.x<_Line.z&&input.wPos.y>ey) { isGray
= true ; } if (_Line.x>_Line.z&&input.wPos.y<ey) { isGray
= true ; } } if (isGray) { float
gray = dot(c.xyz, float3(0.299, 0.587, 0.114)); c.xyz
= float3(gray,gray,gray); } return
c; }
ENDCG
SubShader
{
Pass
{
ZTest
Always Cull Off ZWrite Off CGPROGRAM
#pragma
vertex vert #pragma
fragment frag ENDCG
}
}
Fallback
off } |
7.15更新:
感謝上蒼之冰提供的想法
優化了shader,去除了if語句
01
02
03
04
05
06
07
08
09
10
11
|
float4
c = tex2D(_MainTex, input.uv); float
ey = _ab.x*input.wPos.x + _ab.y; bool
b1 = _Line.y>_Line.w&&input.wPos.x>_Line.x; bool
b2 = _Line.y<_Line.w&&input.wPos.x<_Line.x; bool
b3 = _Line.x<_Line.z&&input.wPos.y>ey; bool
b4 = _Line.x>_Line.z&&input.wPos.y<ey; bool
a1 = (_ab.z==0)&&(b1||b2); bool
a2 = (_ab.z!=0)&&(b3||b4); bool
d = a1||a2; float
gray = dot(c.xyz, float3(0.299, 0.587, 0.114)); c.xyz
*= (!d); c.xyz
+= float3(gray,gray,gray)*d;
|