居然寫出來了就乓,沒想過能寫出來( post by 2018.5
效果
AntiEffect.shader
Shader "Custom/AntiTexture"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
[Enum(Const,1,Gradient,2)] _RenderType ("Render Type", Int) = 1
[Enum(AntiConst,1,AntiInverse,2)] _ColorType ("Color Type", Int) = 1
_Radius ("Radius", Range(0, 10)) = 0.0
_StartPos ("Start Position", Vector) = (0, 0, 0, 0)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
?
sampler2D _MainTex;
half _Radius;
fixed3 _StartPos;
int _RenderType;
int _ColorType;
?
?
#include "UnityCG.cginc"
?
struct a2v
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
?
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD1;
};
?
?
v2f vert (a2v v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.uv = v.uv;
return o;
}
?
bool inRange(float3 pos)
{
return distance(pos, _StartPos.xyz) < _Radius;
}
?
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
?
// improve performance
if (_RenderType == 1)
{
if (_ColorType == 2)
{
col = 1 - col;
}
return col;
}
?
switch(_ColorType)
{
case 1:
if (inRange(i.worldPos))
{
col = 1 - col;
}
break;
case 2:
if (!inRange(i.worldPos))
{
col = 1 - col;
}
break;
}
?
return col;
}
ENDCG
}
}
}
思路
復(fù)制粘貼在車上和旅館里用手機(jī)打的字:
想要實(shí)現(xiàn)的效果
全局?jǐn)嗔?效果
一開始是考慮這樣一個效果筋遭,從某個點(diǎn)(比如player的中心)開始生成一個逐漸變大的球,在球范圍內(nèi)的物體開始產(chǎn)生效果(比如反色)
直接效果
對于一些簡單的情況當(dāng)然是可以做到的桨武,比如物體A要被斷裂,判斷斷裂球是否與A碰撞锈津,從碰撞時在物體的shader傳入幾個參數(shù)(物體a的中心和斷裂中心以計(jì)算斷裂直線軌跡呀酸,還有斷裂傳播速度以獲取半徑),不過由于每幀要判斷頂點(diǎn)或片元是否處于斷裂球內(nèi)琼梆,這樣shader的計(jì)算量會變得相當(dāng)大性誉,可能會遇到一個性能瓶頸。
還有一個問題茎杂,如果只是簡單的貼圖shader還好错览,對于本身shader就很復(fù)雜的物體改寫shader也是一件很痛苦的事情』屯或者說構(gòu)建很復(fù)雜的物體蝗砾,比如一個簡單的人物模型上面就有幾十幾百個子物體,要這樣全部改一遍根本不可能。
而且material和shader是多對一的關(guān)系悼粮,基本上就告別共用material了闲勺。(后記:對于Unity來說,shader即材質(zhì)扣猫,沒有更換shader的說法
間接效果
還有一個更加簡單的辦法菜循,就是使用屏幕后處理。由名思義就是在所有渲染完成申尤,呈現(xiàn)最終屏幕上的最終效果后癌幕,再進(jìn)行最終的處理。
這樣就簡單了昧穿,因?yàn)橹皇翘幚硪粋€tex2d勺远,只要傳入一個平面坐標(biāo)和擴(kuò)散速度,這個shader寫起來就沒有任何難度可言时鸵。但是這樣做就不好控制深度問題胶逢,比如我不想影響被A擋住的B,但是不可能饰潜,因?yàn)橄绕聊缓筇幚碓黉秩綛的話會出現(xiàn)詭異的位置情況初坠。
(補(bǔ)個圖)
這大概就是一個取舍問題。
無論如何彭雾,直接效果還是需要進(jìn)行實(shí)驗(yàn)的碟刺,大致進(jìn)度如下:(回去用那個貓模型為例)
反色材質(zhì)shader → 動態(tài)反色材質(zhì)shader → 加上觸發(fā)器 → 加上傳入?yún)?shù)功能
(然后摸了一周)
這是寫完后的想法:
構(gòu)思這個東西斷斷續(xù)續(xù)大概花了一周的時間,雖然一個很簡單的想法薯酝,但是寫起來不知道為什么那么痛苦半沽。特別是shader的Debug,因?yàn)閟hader幾乎沒有Debug的方法吴菠,只能憑經(jīng)驗(yàn)判斷是哪里出了錯者填。而且shaderlab對于初學(xué)者極不友好,我是在讀了大概不知道多少個例子(而且是很陳舊的例子)之后橄务,在腦子中推斷語法幔托,還要時時刻刻考慮性能問題。上面的代碼我給出了一個_RenderType
蜂挪,從而在非碰撞時重挑,設(shè)計(jì)一個能夠跳過片元著色器的邏輯判斷的分支。
擴(kuò)展閱讀
感謝下列文章棠涮,雖然無法根本解決問題谬哀,但是為我提供了寶貴的思考價值:
【鏈接】UnityShader使用枚舉切換整體色調(diào)https://blog.csdn.net/chy555chy/article/details/79065485
【鏈接】【貓貓的UnityShader之旅】之使用頂點(diǎn)的世界坐標(biāo)https://blog.csdn.net/dbtxdxy/article/details/45679371
【鏈接】unity幾種優(yōu)化建議https://blog.csdn.net/ElyXiao/article/details/51980863
以及《Unity Shader入門精要》,從附帶的代碼中解決了我絕大多數(shù)的困惑