1.遮罩的意義,就是讓某個顏色的部分透明,其他的不透明。
實現思路很簡單,但如果你是從這個系列一步一步上學過來的,那肯定很簡單啦
1.1我們先定義一個標準Shader,然後慢慢改
Shader "Custom/Mask001" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
關於surf函數,起點,和終點的問題,在前面有過介紹。但是這裏我們不喜歡用這玩意。刪掉。我們還是兩個過程
1.頂點着色
2.片元着色
1.2 我們先改出一個簡單的渲染流水線。
Shader "Custom/Mask001" {
Properties {
//遮罩圖
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader{
Tags { "RenderType" = "Opaque" }
LOD 200
Pass{
CGPROGRAM
//定義頂點着色器
#pragma vertex vertex
//定義片元着色器
#pragma fragment fragment
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
#include "UnityCG.cginc"
#include "Lighting.cginc"
//CG變量的遮罩圖,你可以調用這個變量的數據,並通過前面章節提供的函數進行採樣
sampler2D _MainTex;
//來自於cpu的數據模型
struct fromCpu {
//傳入的mesh的基本組成:頂點和UV
};
//來自頂點着色器的數據模型
struct v2f {
//傳入的mesh的基本組成:頂點和UV
};
//運行頂點着色器,輸入data數據,輸出計算後的數據。注意流水線
v2f vertex(fromCpu data) {
}
//運行片元着色器,返回最終計算出來的顏色數據,輸入是頂點着色器的輸出。
fixed4 fragment(v2f data) : SV_Target{
}
ENDCG
}
}
FallBack "Diffuse"
}
1.3我們改出了這個流水線後,直接返回一個簡單的顏色作爲測試
1.我們得思考從緩存中將什麼數據丟到流水線裏面?
mesh的頂點
mesh的uv
Shader "Custom/Mask001" {
Properties {
//遮罩圖
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader{
Tags { "RenderType" = "Opaque" }
LOD 200
Pass{
CGPROGRAM
//定義頂點着色器
#pragma vertex vertex
//定義片元着色器
#pragma fragment fragment
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
#include "UnityCG.cginc"
#include "Lighting.cginc"
//CG變量的遮罩圖,你可以調用這個變量的數據,並通過前面章節提供的函數進行採樣
sampler2D _MainTex;
//來自於cpu的數據模型
struct fromCpu {
//傳入的mesh的基本組成:頂點和UV
fixed4 vertex : POSITION;
float2 uv:TEXCOORD0;
};
//來自頂點着色器的數據模型
struct v2f {
//傳入的mesh的基本組成:頂點和UV
fixed4 vertex : POSITION;
float2 uv:TEXCOORD0;
};
//運行頂點着色器,輸入data數據,輸出計算後的數據。注意流水線
v2f vertex(fromCpu data) {
v2f o;
//轉到世界座標
o.vertex = UnityObjectToClipPos(data.vertex);
return o;
}
//運行片元着色器,返回最終計算出來的顏色數據,輸入是頂點着色器的輸出。
fixed4 fragment(v2f data) : SV_Target{
return fixed4(0,1,0,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
此時的效果如下:
1.4 我們希望採樣一張圖片
既然是採樣圖片,那你就得有uv,uv存放在哪?存放在內存裏,也就是vertex着色操作裏面輸入的fromCpu的結構體。
你得把它傳過來!!!,然後用tex2D(_MainTex,data.uv)進行採樣,返回就可以啦!
Shader "Custom/Mask001" {
Properties {
//遮罩圖
_MainTex("Texture", 2D) = "white" {}
}
SubShader{
Tags { "RenderType" = "Opaque" }
LOD 200
Pass{
CGPROGRAM
//定義頂點着色器
#pragma vertex vertex
//定義片元着色器
#pragma fragment fragment
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
#include "UnityCG.cginc"
#include "Lighting.cginc"
//CG變量的遮罩圖,你可以調用這個變量的數據,並通過前面章節提供的函數進行採樣
sampler2D _MainTex;
//來自於cpu的數據模型
struct fromCpu {
//傳入的mesh的基本組成:頂點和UV
fixed4 vertex : POSITION;
float2 uv:TEXCOORD0;
};
//來自頂點着色器的數據模型
struct v2f {
//傳入的mesh的基本組成:頂點和UV
fixed4 vertex : POSITION;
float2 uv:TEXCOORD0;
};
//運行頂點着色器,輸入data數據,輸出計算後的數據。注意流水線
v2f vertex(fromCpu data) {
v2f o;
//轉到世界座標
o.vertex = UnityObjectToClipPos(data.vertex);
o.uv = data.uv;
return o;
}
half4 c1;
//運行片元着色器,返回最終計算出來的顏色數據,輸入是頂點着色器的輸出。
fixed4 fragment(v2f data) : SV_Target{
c1 = tex2D(_MainTex,data.uv);
return c1;
}
ENDCG
}
}
FallBack "Diffuse"
}
現在展示的效果如下:
1.5 現在,問題來了,我們要採樣的數據是UI的Image的Sprite數據
我們定義的片元操作如下:
我們給_MainTex賦值的貼圖如下:
此時Mesh顯示出來的效果居然是UI的Image的Sprite
也就是:
按道理不應該是,比如一個cube這種:
但是,如果我將Image的Sprite設置爲空,顯示效果如下:
然後經過我們種種測試之後,真相只有一個:
在Image的材質的2D採樣中,當你對名稱爲“_MainTex”進行採樣時,採樣數據優先採樣Image的Sprite!
就是上面這個。
然後,我們來驗證,此時的效果
當我定義名稱爲_MainTex的屬性後,我們的UI效果:
當我定義_MainTex1的屬性後:
結果則:
所以,我們可以採樣到當前UI的Sprite的圖像 。
而能夠採樣到這個圖像,那麼你在片元裏面就能夠修飾這個圖像的數據,也就是最終的遮罩!
代碼如下:
Shader "Custom/Mask001" {
Properties {
_MainTex("ts", 2D) = "white" {}
_Mask("Mask",2D) = "white"{}
}
SubShader{
Tags {
"Queue" = "Transparent"
}
LOD 200
Pass{
//開啓混合
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
//定義頂點着色器
#pragma vertex vertex
//定義片元着色器
#pragma fragment fragment
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
#include "UnityCG.cginc"
#include "Lighting.cginc"
//CG變量的遮罩圖,你可以調用這個變量的數據,並通過前面章節提供的函數進行採樣
sampler2D _Mask;
sampler2D _MainTex;
//來自於cpu的數據模型
struct fromCpu {
//傳入的mesh的基本組成:頂點和UV
fixed4 vertex : POSITION;
float2 uv:TEXCOORD0;
float4 color : COLOR;
};
//來自頂點着色器的數據模型
struct v2f {
//傳入的mesh的基本組成:頂點和UV
fixed4 vertex : POSITION;
float2 uv:TEXCOORD0;
float4 color : COLOR;
};
//運行頂點着色器,輸入data數據,輸出計算後的數據。注意流水線
v2f vertex(fromCpu data) {
v2f o;
//轉到世界座標
o.vertex = UnityObjectToClipPos(data.vertex);
o.uv = data.uv;
//o.color = data.color;
return o;
}
half4 c1;
half4 c2;
//運行片元着色器,返回最終計算出來的顏色數據,輸入是頂點着色器的輸出。
fixed4 fragment(v2f data) : SV_Target{
c1 = tex2D(_MainTex,data.uv);
c2 = tex2D(_Mask, data.uv);
c2.a = c2.r;
return c1*c2;
}
ENDCG
}
}
FallBack "Diffuse"
}
遮罩圖如下:
對於ts來說本身是沒有意義的,所以,我們可以隱藏掉。可以使用
[PerRendererData]
關鍵字:
然後,貼圖選項裏面:
就只有遮罩圖了。