一、計(jì)算機(jī)圖形學(xué)
1. 概述
- Unity的代碼在CPU中運(yùn)行,圖形學(xué)的代碼在GPU中運(yùn)行
- 圖形學(xué)使用CG(C Graph)語(yǔ)言,是英偉達(dá)和微軟聯(lián)合開(kāi)發(fā)的跨平臺(tái)語(yǔ)言
- 操作系統(tǒng)中的圖形處理軟件DX12,使用GLSL(OpenGL Shading Language)、DX語(yǔ)言
- shader 1.0實(shí)現(xiàn)的功能很少,更像設(shè)置參數(shù);shader 2.0,為開(kāi)發(fā)者留下了開(kāi)發(fā)接口,可以進(jìn)行可編程式的開(kāi)發(fā);Unity的shader,表面著色器,介于1.0和2.0之間,翻譯成2.0然后發(fā)給GPU
- shader 1.0 :固定管線著色器、shader 2.0:頂點(diǎn)片段著色器、Unity shader:表面著色器
- shader:著色器,使用紋理、數(shù)據(jù)、顏色等原材料,通過(guò)編程的方式進(jìn)行一些邏輯運(yùn)算,設(shè)置到材質(zhì)球上
- 寫(xiě)shader,要使用的原材料盡量可以變化,適應(yīng)多種平臺(tái)多種需求
2. 渲染繪圖管線
- 圖像從GPU里的體現(xiàn)過(guò)程:一個(gè)個(gè)頂點(diǎn)連線,組成三角形作為面,由面拼成一個(gè)圖形。
- 繪圖流程:頂點(diǎn)處理、面處理、光柵化、像素處理
2.1 頂點(diǎn)處理
頂點(diǎn)處理就是坐標(biāo)轉(zhuǎn)換,將物體的本地坐標(biāo)最終轉(zhuǎn)換成屏幕坐標(biāo)
- 坐標(biāo)按這四種坐標(biāo)系的順序進(jìn)行轉(zhuǎn)換:本地坐標(biāo),世界坐標(biāo),觀察坐標(biāo)系,投影坐標(biāo)系
- unity中拼合的頂點(diǎn)分開(kāi)算頂點(diǎn),例如一個(gè)Cube有4 * 6 = 24個(gè)頂點(diǎn)
2.2 面的處理
- 面組裝:將頂點(diǎn)處理得到的點(diǎn)集合進(jìn)行處理,把點(diǎn)連成面
- 面截?。哼B成面之后,判斷哪些在屏幕范圍,將這些面截取
- 面剔除:面截取后,判斷哪些面會(huì)被別的面擋住,顯示不出來(lái),將這些面剔除
2.3 光柵化
- 將面處理得到的面轉(zhuǎn)換成一個(gè)個(gè)像素,稱為光柵化
- 邊緣鋸齒等問(wèn)題出在這步
2.4 像素處理
輸入像素的位置、深度、貼圖坐標(biāo)、法線、切線、顏色等,給像素著色,使用四通道RGBA
2.5 shader各版本能做的事情
- shader 1.0:像素處理
- shader 2.0:像素處理、頂點(diǎn)處理
3. 固定管線著色器(Fixed Shader、Shader 1.0)
每有一個(gè)像素,就執(zhí)行一次
3.1 結(jié)構(gòu)
// Shader關(guān)鍵字 路徑
Shader "AShader/FixedShader/Base001"{
// 屬性模塊
Properties
{
}
// 子著色器,可以有多個(gè),作用是面對(duì)不同的設(shè)備,從上到下做嘗試
// 質(zhì)量高,渲染效果好的,性能消耗大的
SubShader
{
// 通道1
Pass
{
}
// 通道2
Pass
{
}
}
// 中等質(zhì)量
SubShader
{
Pass
{
}
}
// 質(zhì)量差
SubShader
{
Pass
{
}
}
// 最基礎(chǔ)的,Unity 4.x 預(yù)設(shè)的漫反射
Fallback "Diffuse"
}
3.2 屬性
Properties
{
// 屬性定義語(yǔ)法:屬性名("面板顯示名稱",屬性類(lèi)型) = 初值
// 浮點(diǎn)型(使用較少)
_FloatValue("浮點(diǎn)數(shù)", float) = 0.5
// 范圍浮點(diǎn)型(常用)
_RangeValue("范圍浮點(diǎn)數(shù)", Range(0, 100)) = 30
// 四維數(shù) (x, y, z, w) (使用較少)
_VectorValue("四維數(shù)", Vector) = (1, 1, 1, 1)
// 顏色,范圍[0 - 1](常用)
_ColorValue("顏色值", Color) = (1, 0, 0, 1)
// 2階貼圖,材質(zhì)的長(zhǎng)寬是2的多少次冪 2x2 4x4 8x8 16x16(常用)
// Tiling x, y :平鋪
// Offset x, y :起始位置
_MainTexture("主紋理", 2D) = ""{}
// 非2階貼圖(使用較少)
_RectTexture("非2階紋理", Rect) = ""{}
// 立方體貼圖 6個(gè)紋理,每個(gè)紋理表示一個(gè)面(使用很少)
_CubeTexture("3D紋理", Cube) = ""{}
}
3.3 命令
- Tag命令
寫(xiě)在SubShader中
// 標(biāo)簽
Tags
{
// 渲染隊(duì)列,數(shù)字越小越先渲染,數(shù)字大的會(huì)擋住數(shù)字小的
// 隊(duì)列在賦值的時(shí)候可以使用運(yùn)算,但是是字符串賦值,所以+號(hào)左右不能有空格
"Queue" = "Transparent+1"
}
預(yù)設(shè)的四種渲染隊(duì)列級(jí)別
| 級(jí)別 | 翻譯 | 代表數(shù)字 |
|---|---|---|
| Background | 后臺(tái) | 1000 |
| Geometry(默認(rèn)) | 幾何體 | 2000 |
| Transparent | 透明 | 3000 |
| Overlay | 覆蓋 | 4000 |
- 渲染命令
寫(xiě)在Pass(通道)中
| 命令 | 作用 |
|---|---|
| Color(r, g, b, a) | 用指定顏色渲染 |
| Color[Color] | 用屬性顏色渲染 |
| Lighting On/Off | 開(kāi)啟/關(guān)閉頂點(diǎn)光照 |
| Cull Front/Back/Off | 剔除正面/剔除背面/關(guān)閉剔除 |
| ZWrite On/Off(默認(rèn)為On) | 是否要將像素的深度寫(xiě)入深度緩存中 |
| ZTest Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off(默認(rèn)為L(zhǎng)Equal) | 通過(guò)比較深度來(lái)更改深度緩存的值,Always指的是直接將當(dāng)前像素顏色(不是深度)寫(xiě)進(jìn)顏色緩沖區(qū)中,Never指的是永遠(yuǎn)不會(huì)將當(dāng)前像素顏色寫(xiě)進(jìn)顏色緩沖區(qū)中,相當(dāng)于消失,Off指的是關(guān)閉深度測(cè)試 |
| SeparateSpecular On/Off | 鏡面反射開(kāi)啟/關(guān)閉 |
利用渲染隊(duì)列修改顯示順序
Shader "AShader/FixedShader/Fixed003"
{
Properties
{
_MainColor("主顏色", Color) = (1, 1, 1, 1)
}
SubShader
{
// 標(biāo)簽
Tags
{
// 渲染隊(duì)列
"Queue" = "Transparent+1"
}
Pass
{
// 關(guān)閉深度測(cè)試
ZTest Off
Lighting On
Material
{
Diffuse[_MainColor]
}
}
}
}
- 透明混合命令
| 命令 | 作用 |
|---|---|
| Blend SrcAlpha OneMinusSrcAlpha | 透明混合,有時(shí)候后面的東西會(huì)消失,不穩(wěn)定,基本不在shader 1.0中使用 |
| Blend One One | 相加,主顏色更亮 |
| Blend One OneMinusDstColor | 更柔和的相加 |
| Blend DstColor Zero | 相乘 |
| Blend DstColor SrcColor | 2倍乘法 |
Shader "AShader/FixedShader/Fixed009"{
Properties
{
_MainTexture("主紋理", 2D) = ""{}
}
SubShader
{
// 透明混合
//Blend SrcAlpha OneMinusSrcAlpha
//Blend One One
//Blend One OneMinusDstColor
//Blend DstColor Zero
Blend DstColor SrcColor
Pass
{
SetTexture[_MainTexture]
{
combine texture
}
}
}
}
- Alpha測(cè)試命令
| 命令 | 作用 |
|---|---|
| AlphaTest Off | 關(guān)閉 |
| AlphaTest Greater | 大于 |
| AlphaTest GEqual | 大于等于 |
| AlphaTest Less | 小于 |
| AlphaTest LEqual | 小于等于 |
| AlphaTest Equal | 等于 |
| AlphaTest NotEqual | 不等于 |
| AlphaTest Always | 渲染所有像素 |
| AlphaTest Never | 不渲染任何像素 |
Shader "AShader/FixedShader/Fixed008"{
Properties
{
_AlphaTest("透明測(cè)試", Range(0, 1)) = 1
_MainTexture("主紋理", 2D) = ""{}
}
SubShader
{
Pass
{
// 溶解效果
AlphaTest Greater [_AlphaTest]
SetTexture[_MainTexture]
{
combine texture
}
}
}
}
- Material 材質(zhì)命令
寫(xiě)在Pass -> Material中
| 命令 | 作用 |
|---|---|
| Diffuse[Color] | 漫反射顏色 |
| Ambient[Color] | 環(huán)境光反射顏色 |
| Shininess[float] | 光澤度 |
| Specular[Color] | 高光顏色 |
| Emission[Color] | 自發(fā)光顏色 |
Shader "AShader/FixedShader/Fixed006"{
Properties
{
_MainColor("主顏色", Color) = (1, 1, 1, 1)
_SpecularColor("高光顏色", Color) = (1, 1, 1 ,1)
_Shininess("光澤度", Range(0.1, 1)) = 0.5
_Ambient("環(huán)境光顏色", Color) = (1, 1, 1, 1)
_Emission("自發(fā)光顏色", Color) = (1, 1, 1, 1)
}
SubShader
{
Pass
{
Color[_MainColor]
Lighting On
SeparateSpecular On
Material
{
Diffuse[_MainColor]
Specular[_SpecularColor]
Shininess[_Shininess]
Ambient[_AmbientColor]
Emission[_EmissionColor]
}
}
}
}
- Texture 紋理命令
紋理命令寫(xiě)在Pass中,紋理命令不區(qū)分大小寫(xiě)
SetTexture[Texture]
{
// 定義constantColor
constantColor(r, g, b, a)
constantColor[Color]
// 合并命令
// 因?yàn)镽GBA的值范圍是[0 - 1],所以 + 更趨向于(1, 1, 1, 1)(白色)更亮,* 更趨向于(0, 0, 0, 0)(黑色)更暗
combine src1 + src2
combine src1 * src2
// -src 為補(bǔ)色
combine src1 - src2
// 使用src2的透明通道值在src1和src3之間取插值,插值是反向的,透明度為0的時(shí)候取src3,透明度為1的時(shí)候取src1
combine src1 lerp(src2) src3
}
| 源類(lèi)型(src) | 描述 |
|---|---|
| primary | 來(lái)自光照計(jì)算的顏色或是當(dāng)它綁定時(shí)的頂點(diǎn)顏色 |
| texture | 在SetTexture中定義的紋理的顏色 |
| previous | 上一次SetTexture的結(jié)果 |
| constant | 被constantColor定義的顏色 |
- 兩張紋理圖漸變切換
Fixed007.shader
Shader "AShader/FixedShader/Fixed007"{
Properties
{
_LerpScale("插值比例", Range(0, 1)) = 1
_MainTexture("主紋理", 2D) = ""{}
_DetailTexture("細(xì)節(jié)紋理", 2D) = ""{}
}
SubShader
{
Pass
{
SetTexture[_MainTexture]
{
constantColor(1, 0, 0, 0)
}
SetTexture[_DetailTexture]
{
constantColor(1, 1, 1, [_LerpScale])
combine texture lerp(constant) previous
}
}
}
}
SkinLerp.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SkinLerp : MonoBehaviour
{
// 拿到meshRenderer
private MeshRenderer _meshRenderer;
// 當(dāng)前的lerpScale
private float lerpScale;
// 目標(biāo)lerpScale
private float targetScale;
private void Awake()
{
_meshRenderer = GetComponent<MeshRenderer>();
}
private void Update()
{
// 取插值
lerpScale = Mathf.Lerp(lerpScale, targetScale, Time.deltaTime * 2);
// 0 - 1 之間來(lái)回切換
if (Mathf.Abs(lerpScale - targetScale) < 0.05)
targetScale = (targetScale == 0) ? 1 : 0;
// 使用代碼控制
// name : 屬性名
// value : 值
_meshRenderer.material.SetFloat("_LerpScale", lerpScale);
// 修改Offset使圖片動(dòng)起來(lái)
_meshRenderer.material.SetTextureOffset("_MainTexture", new Vector2(Time.time, 0));
_meshRenderer.material.SetTextureOffset("_DetailTexture", new Vector2(-Time.time, 0));
}
}
4. 表面著色器(Surface Shader)
4.1 CG語(yǔ)言
-
基本數(shù)據(jù)類(lèi)型(所有的數(shù)據(jù)類(lèi)型后面都可以加數(shù)字,表示多個(gè)該類(lèi)型的,類(lèi)似Vector)
- float:32位 浮點(diǎn)數(shù)
- float2:2個(gè)浮點(diǎn)數(shù)
- float3:3個(gè)浮點(diǎn)數(shù)
- float4:4個(gè)浮點(diǎn)數(shù)
- half:16位 浮點(diǎn)數(shù)
- int:32位 整型
- fixed:12位 定點(diǎn)數(shù),取值范圍 [0 - 1] 的小數(shù) 或 整數(shù)
- bool
- sampler2D:紋理對(duì)象
- string
- float:32位 浮點(diǎn)數(shù)
-
預(yù)設(shè)的Structure
-
輸入
變量名 代表內(nèi)容 float2 uv_MainTex 紋理貼圖UV,模型上每個(gè)像素對(duì)應(yīng)到紋理圖的坐標(biāo),_MainTex為紋理圖的名字 float3 viewDir 像素的視圖方向 float3 worldPos 像素的世界坐標(biāo)位置 float4 screenPos 屏幕空間位置,是float4類(lèi)型,只需用前兩個(gè)值 float4 color:COLOR 每個(gè)頂點(diǎn)的內(nèi)插值顏色 -
輸出
變量名 代表內(nèi)容 half3 Albedo 反射率,即顏色紋理RGB half3 Normal 法線,即法向量(x, y, z) half3 Emission 自發(fā)光顏色RGB half Specular 鏡面反射度 half Gloss 光澤度 half Alpha 透明度
-
語(yǔ)義綁定
語(yǔ)法:變量名:語(yǔ)義定義,表示這個(gè)變量代表著某種指定的值,例:color:COLOR表示color這個(gè)變量是顏色
4.2 結(jié)構(gòu)
- 表面著色器沒(méi)有Pass通道
- 外部是Shader Lab,內(nèi)部嵌入CG語(yǔ)言
Shader "Ashader/SurfaceShader/Shader001"
{
Properties
{
}
SubShader
{
// 不需要Pass通道
// 預(yù)編譯指令 粉色高亮
// --------- CG語(yǔ)言開(kāi)始 ---------
CGPROGRAM
// 表面著色器 入口函數(shù)名稱 蘭伯特光照模型(漫反射)
#pragma surface surf Lambert
// 輸入結(jié)構(gòu)體
struct Input
{
float3 viewDir;
}; // CG語(yǔ)言結(jié)構(gòu)體定義后要加";"
// 聲明外部屬性,要求和屬性名字相同
fixed4 _MainColor;
// 入口函數(shù)
// 參數(shù)
// Input IN : 輸入結(jié)構(gòu)體
// in/out/inout SurfaceOutput o : 常用于輸出
// in:輸入 out:輸出 inout:既能輸入又能輸出
void surf(Input IN, inout SurfaceOutput o)
{
// 輸出純色
o.Albedo = float3(1, 0, 0);
// 四個(gè)數(shù)字rgba或xyzw 轉(zhuǎn)三個(gè)數(shù)字:變量.rgb .gba .xyz .yzw,用到哪個(gè)寫(xiě)哪個(gè)
o.Albedo = _MainColor.rgb;
}
// --------- CG語(yǔ)言結(jié)束 ---------
ENDCG
}
}
4.3 方法使用
- 設(shè)置紋理圖
Shader "AShader/SurfaceShader/Surface002"
{
Properties
{
_MainTexture("主紋理", 2D) = ""{}
_MainColor("主顏色", Color) = (1, 1, 1, 1)
}
SubShader
{
// --------- CG語(yǔ)言開(kāi)始 ---------
CGPROGRAM
// 表面著色器 入口函數(shù)名稱 蘭伯特光照模型(漫反射)
#pragma surface surf Lambert
// 聲明外部屬性
sampler2D _MainTexture;
fixed4 _MainColor;
// 輸入結(jié)構(gòu)體
struct Input
{
// 主紋理的UV坐標(biāo)
float2 uv_MainTexture;
};
// 入口函數(shù)
void surf(Input IN, inout SurfaceOutput o)
{
// 渲染紋理圖,通過(guò)UV坐標(biāo)在紋理貼圖中獲取當(dāng)前像素點(diǎn)的顏色值
// 參數(shù)
// _MainTexture:紋理圖
// IN.uv_MainTexture:紋理圖UV
o.Albedo = tex2D(_MainTexture, IN.uv_MainTexture).rgb;
// 與顏色進(jìn)行混合
o.Albedo *= _MainColor.rgb;
}
// --------- CG語(yǔ)言結(jié)束 ---------
ENDCG
}
}
- 設(shè)置法線貼圖
Shader "AShader/SurfaceShader/Surface003"
{
Properties
{
_MainTexture("主紋理", 2D) = ""{}
_NormalTexture("法線紋理", 2D) = ""{}
}
SubShader
{
// --------- CG語(yǔ)言開(kāi)始 ---------
CGPROGRAM
// 表面著色器 入口函數(shù)名稱 蘭伯特光照模型(漫反射)
#pragma surface surf Lambert
// 聲明外部屬性
sampler2D _MainTexture;
sampler2D _NormalTexture;
// 輸入結(jié)構(gòu)體
struct Input
{
// 主紋理的UV坐標(biāo)
float2 uv_MainTexture;
float2 uv_NormalTexture;
};
// 入口函數(shù)
void surf(Input IN, inout SurfaceOutput o)
{
// 渲染紋理圖,通過(guò)UV坐標(biāo)在紋理貼圖中獲取當(dāng)前像素點(diǎn)的顏色值
// 參數(shù)
// _MainTexture:紋理圖
// IN.uv_MainTexture:紋理圖UV
o.Albedo = tex2D(_MainTexture, IN.uv_MainTexture).rgb;
// 設(shè)置法線貼圖
o.Normal = UnpackNormal(tex2D(_NormalTexture, IN.uv_NormalTexture));
}
// --------- CG語(yǔ)言結(jié)束 ---------
ENDCG
}
}
- 邊緣發(fā)光
Shader "AShader/SurfaceShader/Surface004"
{
Properties
{
_MainTexture("主紋理", 2D) = ""{}
_NormalTexture("法線紋理", 2D) = ""{}
_RimColor("發(fā)光顏色", Color) = (1, 1, 1, 1)
_RimPower("發(fā)光強(qiáng)度", Range(1, 10)) = 1
}
SubShader
{
// --------- CG語(yǔ)言開(kāi)始 ---------
CGPROGRAM
// 表面著色器 入口函數(shù)名稱 蘭伯特光照模型(漫反射)
#pragma surface surf Lambert
// 聲明外部屬性
sampler2D _MainTexture;
sampler2D _NormalTexture;
fixed4 _RimColor;
half _RimPower;
// 輸入結(jié)構(gòu)體
struct Input
{
// 主紋理的UV坐標(biāo)
float2 uv_MainTexture;
float2 uv_NormalTexture;
// 視圖方向
float3 viewDir;
};
// 入口函數(shù)
void surf(Input IN, inout SurfaceOutput o)
{
// 渲染紋理圖,通過(guò)UV坐標(biāo)在紋理貼圖中獲取當(dāng)前像素點(diǎn)的顏色值
// 參數(shù)
// _MainTexture:紋理圖
// IN.uv_MainTexture:紋理圖UV
o.Albedo = tex2D(_MainTexture, IN.uv_MainTexture).rgb;
// 設(shè)置法線貼圖
o.Normal = UnpackNormal(tex2D(_NormalTexture, IN.uv_NormalTexture));
// 計(jì)算邊緣發(fā)光系數(shù)
float rim = 1 - saturate(dot(normalize(IN.viewDir), normalize(o.Normal)));
// 系數(shù)直接乘
//o.Emission = _RimColor * rim * _RimPower;
// 系數(shù)的光強(qiáng)次冪
o.Emission = _RimColor * pow(rim, 10 - _RimPower);
}
// --------- CG語(yǔ)言結(jié)束 ---------
ENDCG
}
}
5. 頂點(diǎn)片段著色器(Shader 2.0)
5.1 頂點(diǎn)語(yǔ)義
* model本地坐標(biāo)
* view觀察坐標(biāo)
* projection投影坐標(biāo)
| 語(yǔ)義 | 代表內(nèi)容 |
|---|---|
| float4 POSITION | 頂點(diǎn)坐標(biāo)位置 |
| float3 NORMAL | 頂點(diǎn)法線向量坐標(biāo) |
| float4 TEXCOORD0 | 第一個(gè)UV坐標(biāo)(用作臨時(shí)變量,存坐標(biāo)存顏色等) |
| float4 TEXCOORD1/2/3... | 第二/三/四...個(gè)UV坐標(biāo) |
| float4 TENGENT | 頂點(diǎn)切線向量坐標(biāo) |
| float4 COLOR | 頂點(diǎn)顏色值 |
5.2 常用函數(shù)庫(kù)
| 庫(kù)名 | 作用 |
|---|---|
| HLSLSupport.cginc | 輔助為跨平臺(tái)的著色器編譯宏和定義 |
| UnityShaderVariables.cginc | 常用全局變量 |
| UnityCG.cginc | 常用輔助函數(shù) |
| AutoLight.cginc | 光、影函數(shù) |
| Lighting.cginc | 光照模型相關(guān) |
| TerrainEngine.cginc | 地形植被輔助 |
5.3 結(jié)構(gòu)
Shader "AShader/VFShader/VF001"
{
Properties
{
_MainColor("主顏色", Color) = (1, 1, 1, 1)
}
SubShader
{
Pass
{
CGPROGRAM
// 著色器類(lèi)型 入口函數(shù)名稱
#pragma vertex vert
#pragma fragment frag
// 聲明外部屬性
fixed4 _MainColor;
// 頂點(diǎn)著色器,進(jìn)行頂點(diǎn)處理
// 返回值 入口函數(shù)名稱(參數(shù)類(lèi)型 參數(shù)名:語(yǔ)義綁定):返回值語(yǔ)義綁定
float4 vert(float4 vertexPos:POSITION):SV_POSITION
{
// 完成頂點(diǎn)變換,返回投影坐標(biāo)
// 5.4之前
//return mul(UNITY_MATRIX_MVP, vertexPos);
// 5.4之后
return UnityObjectToClipPos(vertexPos);
}
// 片段著色器,著色
fixed4 frag():COLOR
{
//return fixed4(1, 0, 0, 1);
return _MainColor;
}
ENDCG
}
}
}
5.4 案例
- 彩虹顏色
將物體的坐標(biāo)作為顏色值,會(huì)呈現(xiàn)彩虹效果
Shader "AShader/VFShader/VF002"
{
Properties
{
_ColorOffset("顏色偏移量", Range(0, 1)) = 0
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 聲明外部屬性變量
fixed _ColorOffset;
// 由于return只能返回一個(gè)變量,所以當(dāng)想返回多個(gè)值的時(shí)候使用結(jié)構(gòu)體
// 頂點(diǎn)著色器輸出的結(jié)構(gòu)體
struct v2f
{
// 0級(jí)紋理坐標(biāo)(臨時(shí)變量,用于存儲(chǔ)頂點(diǎn)著色器算出來(lái)的頂點(diǎn)坐標(biāo),給片段著色器用)
float4 col:TEXCOORD0;
// 屏幕坐標(biāo)
float4 pos:SV_POSITION;
};
// 頂點(diǎn)著色器入口函數(shù)
v2f vert(float4 vertexPos:POSITION)
{
// 定義結(jié)構(gòu)體對(duì)象
v2f content;
// 執(zhí)行頂點(diǎn)變換
content.pos = UnityObjectToClipPos(vertexPos);
// 獲取頂點(diǎn)坐標(biāo)
content.col = vertexPos + float4(_ColorOffset, _ColorOffset, _ColorOffset, 0);
return content;
}
// 片段著色器入口函數(shù)
float4 frag(v2f content):COLOR
{
// 將頂點(diǎn)坐標(biāo)當(dāng)成顏色值輸出
return content.col;
}
ENDCG
}
}
}
- 設(shè)定漫反射
Shader "AShader/VFShader/VF003"
{
Properties
{
_MainColor("漫反射顏色", COLOR) = (1, 1, 1, 1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 引入庫(kù)
#include "UnityCG.cginc"
// 聲明外部變量
fixed4 _MainColor;
// 聲明內(nèi)置變量
fixed4 _LightColor0;
// 頂點(diǎn)著色器輸入結(jié)構(gòu)體
struct appdata
{
// 頂點(diǎn)坐標(biāo)
float4 vertexPos:POSITION;
// 頂點(diǎn)法線
float3 vertexNormal:NORMAL;
};
// 頂點(diǎn)著色器輸出結(jié)構(gòu)體
struct v2f
{
// 屏幕坐標(biāo)
float4 pos:SV_POSITION;
// 屏幕法線
float3 normal:NORMAL;
};
// 頂點(diǎn)著色器入口函數(shù)
v2f vert(appdata data)
{
v2f content;
content.pos = UnityObjectToClipPos(data.vertexPos);
// 計(jì)算法線
content.normal = mul(float4(data.vertexNormal, 1), unity_WorldToObject).xyz;
return content;
}
// 片段著色器入口函數(shù)
fixed4 frag(v2f content):COLOR
{
// 求法線的標(biāo)準(zhǔn)化向量
float3 lightNormal = normalize(content.normal);
// 求入射光的標(biāo)準(zhǔn)化向量
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
// 計(jì)算漫反射顏色
float3 diffuseColor = _MainColor * _LightColor0 * -min(0, dot(lightNormal, lightDir));
return fixed4(diffuseColor, 1) + UNITY_LIGHTMODEL_AMBIENT;
}
ENDCG
}
}
}
- 技能釋放范圍
Shader "SkillShader/Skill1"
{
Properties
{
// 技能釋放原點(diǎn)
_BossPosition("BossPosition", Vector) = (1, 1, 1, 1)
// 透明通道值
_Alpha("BossSkillAlpha", Range(0, 1)) = 0
// 用于代碼控制顯示范圍的值
_Dis("SkillDis", Range(0, 10)) = 0
}
SubShader
{
Pass
{
// 開(kāi)啟透明混合
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 _BossPosition;
float _Alpha;
float _Dis;
struct v2f
{
float4 vertPos:TEXCOORD0;
float4 pos:SV_POSITION;
};
v2f vert(float4 vertexPos:POSITION)
{
v2f content;
content.pos = UnityObjectToClipPos(vertexPos);
content.vertPos = vertexPos;
return content;
}
float4 frag(v2f content):COLOR
{
// 根據(jù)傳入坐標(biāo)計(jì)算需要渲染的地方
if (distance(content.vertPos.z, _BossPosition.z) < _Dis && abs(distance(content.vertPos.x, _BossPosition.x)) < 1)
{
return float4(1, 0, 0, _Alpha);
}
else
{
return float4(1, 0, 0, 0);
}
}
ENDCG
}
}
}
6. 小知識(shí)點(diǎn)
- 法線貼圖:法線決定光的反射方向,法線是一個(gè)向量,向量是vector3,顏色的rgb也是vector3,所以法線貼圖使用顏色來(lái)代表向量(例:紅色(1, 0, 0)代表右)
- 邊緣發(fā)光公式:
RimColor = EmissionColor * (1 - clamp01(dot(normalize(normal), normalize(viewDir))))
附:Shader詞典
| 單詞 | 描述 | 單詞 | 描述 | 單詞 | 描述 |
|---|---|---|---|---|---|
| Shader | 著色器 | Properties | 屬性 | SubShader | 子著色器 |
| Pass | 通道 | Color | 顏色 | Cull | 剔除 |
| ZTest | 深度測(cè)試 | SeparateSpecular | 鏡面反射 | Diffuse | 漫反射 |
| Ambient | 環(huán)境光 | Shininess | 光澤度 | Specular | 高光 |
| Emission | 自發(fā)光 | Combine | 結(jié)合 | Primary | 基本的 |
| Previous | 之前的 | Constant | 恒定的 | Gloss | 光澤度 |
| Vertex | 頂點(diǎn) | Fragment | 片段 |