計(jì)算機(jī)圖形學(xué)與Shader

一、計(jì)算機(jī)圖形學(xué)

1. 概述

  1. Unity的代碼在CPU中運(yùn)行,圖形學(xué)的代碼在GPU中運(yùn)行
  2. 圖形學(xué)使用CG(C Graph)語言,是英偉達(dá)和微軟聯(lián)合開發(fā)的跨平臺語言
  3. 操作系統(tǒng)中的圖形處理軟件DX12,使用GLSL(OpenGL Shading Language)、DX語言
  4. shader 1.0實(shí)現(xiàn)的功能很少,更像設(shè)置參數(shù);shader 2.0,為開發(fā)者留下了開發(fā)接口,可以進(jìn)行可編程式的開發(fā);Unity的shader,表面著色器,介于1.0和2.0之間,翻譯成2.0然后發(fā)給GPU
  5. shader 1.0 :固定管線著色器、shader 2.0:頂點(diǎn)片段著色器、Unity shader:表面著色器
  6. shader:著色器,使用紋理、數(shù)據(jù)、顏色等原材料,通過編程的方式進(jìn)行一些邏輯運(yùn)算,設(shè)置到材質(zhì)球上
  7. 寫shader,要使用的原材料盡量可以變化,適應(yīng)多種平臺多種需求

2. 渲染繪圖管線

  • 圖像從GPU里的體現(xiàn)過程:一個(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)分開算頂點(diǎn),例如一個(gè)Cube有4 * 6 = 24個(gè)頂點(diǎn)

2.2 面的處理

  1. 面組裝:將頂點(diǎn)處理得到的點(diǎn)集合進(jìn)行處理,把點(diǎn)連成面
  2. 面截?。哼B成面之后,判斷哪些在屏幕范圍,將這些面截取
  3. 面剔除:面截取后,判斷哪些面會被別的面擋住,顯示不出來,將這些面剔除

2.3 光柵化

  • 將面處理得到的面轉(zhuǎn)換成一個(gè)個(gè)像素,稱為光柵化
  • 邊緣鋸齒等問題出在這步

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è),作用是面對不同的設(shè)備,從上到下做嘗試
    // 質(zhì)量高,渲染效果好的,性能消耗大的
    SubShader
    {
        // 通道1
        Pass
        {
            
        }
        
        // 通道2
        Pass
        {
            
        }
    }
    
    // 中等質(zhì)量
    SubShader
    {
        Pass
        {
            
        }
    }
    
    // 質(zhì)量差
    SubShader
    {
        Pass
        {
            
        }
    }
    
    // 最基礎(chǔ)的,Unity 4.x 預(yù)設(shè)的漫反射
    Fallback "Diffuse"
}

3.2 屬性

Properties
{
    // 屬性定義語法:屬性名("面板顯示名稱",屬性類型) = 初值
    
    // 浮點(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ì)的長寬是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命令
    寫在SubShader中
// 標(biāo)簽
Tags
{
    // 渲染隊(duì)列,數(shù)字越小越先渲染,數(shù)字大的會擋住數(shù)字小的
    // 隊(duì)列在賦值的時(shí)候可以使用運(yùn)算,但是是字符串賦值,所以+號左右不能有空格
    "Queue" = "Transparent+1"
}

預(yù)設(shè)的四種渲染隊(duì)列級別

級別 翻譯 代表數(shù)字
Background 后臺 1000
Geometry(默認(rèn)) 幾何體 2000
Transparent 透明 3000
Overlay 覆蓋 4000
  • 渲染命令
    寫在Pass(通道)中
命令 作用
Color(r, g, b, a) 用指定顏色渲染
Color[Color] 用屬性顏色渲染
Lighting On/Off 開啟/關(guān)閉頂點(diǎn)光照
Cull Front/Back/Off 剔除正面/剔除背面/關(guān)閉剔除
ZWrite On/Off(默認(rèn)為On) 是否要將像素的深度寫入深度緩存中
ZTest Greater/GEqual/Less/LEqual/Equal/NotEqual/Always/Never/Off(默認(rèn)為LEqual) 通過比較深度來更改深度緩存的值,Always指的是直接將當(dāng)前像素顏色(不是深度)寫進(jìn)顏色緩沖區(qū)中,Never指的是永遠(yuǎn)不會將當(dāng)前像素顏色寫進(jìn)顏色緩沖區(qū)中,相當(dāng)于消失,Off指的是關(guān)閉深度測試
SeparateSpecular On/Off 鏡面反射開啟/關(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)閉深度測試
            ZTest Off

            Lighting On

            Material
            {
                Diffuse[_MainColor]
            }
        }
    }
}
  • 透明混合命令
命令 作用
Blend SrcAlpha OneMinusSrcAlpha 透明混合,有時(shí)候后面的東西會消失,不穩(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測試命令
命令 作用
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("透明測試", Range(0, 1)) = 1

        _MainTexture("主紋理", 2D) = ""{}
    }

    SubShader
    {
        Pass
        {
            // 溶解效果
            AlphaTest Greater [_AlphaTest]

            SetTexture[_MainTexture]
            {
                combine texture
            }
        }
    }
}
  • Material 材質(zhì)命令
    寫在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 紋理命令
    紋理命令寫在Pass中,紋理命令不區(qū)分大小寫
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
}
源類型(src) 描述
primary 來自光照計(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 之間來回切換
        if (Mathf.Abs(lerpScale - targetScale) < 0.05)
            targetScale = (targetScale == 0) ? 1 : 0;

        // 使用代碼控制
        // name : 屬性名
        // value : 值
        _meshRenderer.material.SetFloat("_LerpScale", lerpScale);

        // 修改Offset使圖片動起來
        _meshRenderer.material.SetTextureOffset("_MainTexture", new Vector2(Time.time, 0));
        _meshRenderer.material.SetTextureOffset("_DetailTexture", new Vector2(-Time.time, 0));

    }
}

4. 表面著色器(Surface Shader)

4.1 CG語言

  • 基本數(shù)據(jù)類型(所有的數(shù)據(jù)類型后面都可以加數(shù)字,表示多個(gè)該類型的,類似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:紋理對象
    • string
  • 預(yù)設(shè)的Structure

    • 輸入

      變量名 代表內(nèi)容
      float2 uv_MainTex 紋理貼圖UV,模型上每個(gè)像素對應(yīng)到紋理圖的坐標(biāo),_MainTex為紋理圖的名字
      float3 viewDir 像素的視圖方向
      float3 worldPos 像素的世界坐標(biāo)位置
      float4 screenPos 屏幕空間位置,是float4類型,只需用前兩個(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 透明度
  • 語義綁定
    語法:變量名:語義定義,表示這個(gè)變量代表著某種指定的值,例:color:COLOR 表示color這個(gè)變量是顏色

4.2 結(jié)構(gòu)

  • 表面著色器沒有Pass通道
  • 外部是Shader Lab,內(nèi)部嵌入CG語言
Shader "Ashader/SurfaceShader/Shader001"
{
    Properties
    {
        
    }
    
    SubShader
    {
        // 不需要Pass通道

        // 預(yù)編譯指令 粉色高亮
        // --------- CG語言開始 ---------
        CGPROGRAM

        // 表面著色器 入口函數(shù)名稱 蘭伯特光照模型(漫反射)
        #pragma surface surf Lambert

        // 輸入結(jié)構(gòu)體
        struct Input
        {
            float3 viewDir;
        };              // CG語言結(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è)寫哪個(gè)
            o.Albedo = _MainColor.rgb;
        }
        
        // --------- CG語言結(jié)束 ---------
        ENDCG
    }
}

4.3 方法使用

  • 設(shè)置紋理圖
Shader "AShader/SurfaceShader/Surface002"
{
    Properties
    {
        _MainTexture("主紋理", 2D) = ""{}
        _MainColor("主顏色", Color) = (1, 1, 1, 1)
    }

    SubShader
    {
        // --------- CG語言開始 ---------
        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)
        {
            // 渲染紋理圖,通過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語言結(jié)束 ---------
        ENDCG
    }
}
  • 設(shè)置法線貼圖
Shader "AShader/SurfaceShader/Surface003"
{
    Properties
    {
        _MainTexture("主紋理", 2D) = ""{}
        _NormalTexture("法線紋理", 2D) = ""{}
    }

    SubShader
    {
        // --------- CG語言開始 ---------
        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)
        {
            // 渲染紋理圖,通過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語言結(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語言開始 ---------
        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)
        {
            // 渲染紋理圖,通過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語言結(jié)束 ---------
        ENDCG
    }
}

5. 頂點(diǎn)片段著色器(Shader 2.0)

5.1 頂點(diǎn)語義

* model本地坐標(biāo)
* view觀察坐標(biāo)
* projection投影坐標(biāo)
語義 代表內(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ù)庫

庫名 作用
HLSLSupport.cginc 輔助為跨平臺的著色器編譯宏和定義
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

            //      著色器類型 入口函數(shù)名稱
            #pragma vertex vert
            #pragma fragment frag
            // 聲明外部屬性
            fixed4 _MainColor;

            // 頂點(diǎn)著色器,進(jìn)行頂點(diǎn)處理
            // 返回值 入口函數(shù)名稱(參數(shù)類型 參數(shù)名:語義綁定):返回值語義綁定
            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)作為顏色值,會呈現(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級紋理坐標(biāo)(臨時(shí)變量,用于存儲頂點(diǎn)著色器算出來的頂點(diǎn)坐標(biāo),給片段著色器用)
                float4 col:TEXCOORD0;
                // 屏幕坐標(biāo)
                float4 pos:SV_POSITION;
            };

            // 頂點(diǎn)著色器入口函數(shù)
            v2f vert(float4 vertexPos:POSITION)
            {
                // 定義結(jié)構(gòu)體對象
                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
            // 引入庫
            #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
        {
            // 開啟透明混合
            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. 小知識點(diǎn)

  • 法線貼圖:法線決定光的反射方向,法線是一個(gè)向量,向量是vector3,顏色的rgb也是vector3,所以法線貼圖使用顏色來代表向量(例:紅色(1, 0, 0)代表右)
  • 邊緣發(fā)光公式:
    RimColor = EmissionColor * (1 - clamp01(dot(normalize(normal), normalize(viewDir))))

附:Shader詞典

單詞 描述 單詞 描述 單詞 描述
Shader 著色器 Properties 屬性 SubShader 子著色器
Pass 通道 Color 顏色 Cull 剔除
ZTest 深度測試 SeparateSpecular 鏡面反射 Diffuse 漫反射
Ambient 環(huán)境光 Shininess 光澤度 Specular 高光
Emission 自發(fā)光 Combine 結(jié)合 Primary 基本的
Previous 之前的 Constant 恒定的 Gloss 光澤度
Vertex 頂點(diǎn) Fragment 片段
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容