2024-06-11 Unity Shader 开发入门5 —— CG 语法

1 CG 语法基础

1.1 CG 结构

​ 在 Unity 中创建 Unit Shader,打开并观察代码结构。

Shader "Unlit/Lesson13"
{
    Properties {...}
    SubShader
    {
        Tags {...}
        LOD 100

        Pass
        {
            CGPROGRAM // CG 语句从这里开始
                
            #pragma vertex vert   // 表示顶点着色器内容在 vert 函数中
            #pragma fragment frag // 表示片元着色器内容在 frag 函数中
            
            ...
            
            struct appdata {...}; // 数据结构体
            
            struct v2f {...};
            
            ...
            
            v2f vert (appdata v) {...} // 着色器实现函数
            
            fixed4 frag (v2f i) : SV_Target {...}
            
            ENDCG // CG 语句结束
        }
    }
}
  1. 顶点/片元着色器的 CG 语句写在 CGPROGRAMENDCG 之间。

  2. 写 CG 代码前,需要先使用 #pragma 声明编译指令。

    定义实现顶点/片元着色器代码的函数名称:

    • #pragma vertex name(实现顶点着色器的函数名)
    • #pragma fragment name(实现片元着色器的函数名)

    上述两个编译指令的作用是将顶点/片元着色器实现定位到两个函数中。

1.2 数据类型

1.2.1 基础数据类型

类型说明
uint32 位无符号整型
int32 位有符号整型
float32 位浮点数,符号:f
half16 位浮点数,符号:h
fixed12 位浮点数
bool布尔类型
string字符串
sampler通用的纹理采样器,可以用于处理各种不同维度和类型的纹理
sampler1D用于一维纹理,通常用于对一维纹理进行采样,例如从左到右的渐变色
sampler2D用于二维纹理,最常见的纹理类型之一。它用于处理二维图像纹理,例如贴图
sampler3D用于三维纹理,通常用于体积纹理,例如体积渲染
samplerCUBE用于立方体纹理,通常用于处理环境映射等需要立方体贴图的情况
samplerRECT用于处理矩形纹理,通常用于一些非标准的纹理映射需求

1.2.2 复合数据类型

  1. 数组

    • 一维:与 C# 类似。

      int a[4] = {1, 2, 3, 4};

      长度:a.length

    • 二维:

      int b[2][3] = {{1, 2, 3}, {4, 5, 6}};

      长度:b.length = 2,b[0].length = 3。

  2. 结构体

    和 C# 基本一样:

    • 没有访问修饰符。
    • 结构体声明结束加分号。
    • 一般在函数外声明。

1.2.3 特殊数据类型

  1. 向量

    向量类型属于 CG 语言的内置数据类型,最大维度不超过 4,数据类型可以是任意数值类型。

    基本构成:

    • 数据类型2 = 数据类型2(n1, n2);
    • 数据类型3 = 数据类型3(n1, n2, n3);
    • 数据类型4 = 数据类型4(n1, n2, n3, n4);

    示例:

    v2f vert(appdata v)
    {
        v2f o;
    
        int2 i2 = int2(0, 0);
        float3 f3 = float3(0, 0, 0);
        fixed4 f4 = fixed4(0, 0, 0, 0);
    
        return o;
    }
    
  2. 矩阵

    矩阵类型属于 CG 语言的内置数据类型,行列不大于 4,不小于 1,数据类型可以是任意数值类型。

    基本构成:数据类型nxm = {n1m1, n1m2, n1m3, ...};

    示例:

    v2f vert(appdata v)
    {
        v2f o;
    
        int2x3 i2x3 = int2x3(0, 0, 0,
                            0, 0, 0);
        
        float3x3 f3x3 = float3x3{
            0, 0, 0,
            0, 0, 0,
            0, 0, 0
        };
        
        fixed4x4 f4x4 = fixed4x4{
            1, 2, 3, 4,
            5, 6, 7, 8,
            9, 10, 11, 12,
            13, 14, 15, 16
        };
    
        return o;
    }
    
  3. bool 向量 / 矩阵

    bool 类型同样可以用于如同向量一样声明,可以用于存储一些逻辑判断结果。

    float3 a = float3(0.5, 0.0, 1.0);
    float3 b = float3(0.6, -0.1, 0.9);
    bool3 c = a < b;
    

    运算后向量 c 的结果为 bool3(true, false, false)

1.3 操作符

1.3.1 Swizzle 操作符

​ Swizzle 操作符可以用于获取向量中元素,通常以点号(.)的形式使用,后面跟着所需的分量顺序。

​ 对于四维向量,可以通过 向量.xyzw 向量.rgba 两种分量的写法来表示向量中的四个值。

​ 其中 xyzwrgba 分别代表四维向量中的四个元素。

  1. 提取分量
fixed4 f4 = fixed4(1, 2, 3, 4);
fixed f = f4.w; // xyzw
f = f4.a;       // rgba
  1. 重新排列分量
f4 = f4.yzxw;
f4 = f4.abgr;
  1. 创建新向量
fixed3 f3 = f4.xyz;
fixed2 f2 = f3.xz;
fixed4 f4_2 = fixed4(f2, f2);
f4_2 = fixed4(f3, f);

1.3.2 向量/矩阵转换

  1. 向量声明矩阵
fixed4x4 f4x4 = {
    fixed4(1, 2, 3, 4),
    fixed4(1, 2, 3, 4),
    fixed4(1, 2, 3, 4),
    fixed4(1, 2, 3, 4)
};
  1. 获取矩阵元素
f = f4x4[0][0];
  1. 获取矩阵某行
f4_2 = f4x4[3];
  1. 高维转低维
f3 = f4; // 直接使用前面的对应个数的元素,即 f3 = fixed3(f4.x, f4.y, f4.z);
f2 = f4; // f2 = fixed2(f4.x, f4.y);

fixed3x3 f3x3 = f4x4; // f3x3 = fixed3x3(
                      //     f4x4[0][0], f4x4[0][1], f4x4[0][2],
                      //     f4x4[1][0], f4x4[1][1], f4x4[1][2],
                      //     f4x4[2][0], f4x4[2][1], f4x4[2][2],
                      // );

1.4 运算符

  1. 比较运算符

    • >
    • <
    • >=
    • <=
    • ==
    • !=

    CG 中的比较运算符的使用和 C# 一样,运算结果为 bool 值。

  2. 条件运算符

    condition ? value_if_true : value_if_false

    condition 为条件表达式。

    • 如果为真,返回 value_if_true。
    • 否则,返回 value_if_false。
  3. 逻辑运算符

    • ||
    • &&
    • !

    CG 中的逻辑运算符的使用和 C# 一样。

    注意:CG 中不存在 C# 中的"短路"操作。

  4. 数学运算符

    • /
    • %
    • ++

    CG 中的数学运算符的使用和 C# 一样。

    注意:CG 中取余符号只能向整数取余。

1.5 流程控制语句

  1. 条件分支

    • if
    • switch

    条件分支语句的使用和 C# 一模一样。

  2. 循环语句

    • for
    • while
    • do while

    循环语句的使用和 C# 一模一样。

注意:

  1. 尽量少的使用循环语句。如果一定要用,要减少次数和复杂度。
  2. 要利用 GPU 并行性这一特点来替代循环。
  3. 尽量避免复杂的条件分支。

1.6 函数

​ CG 语法中的函数声明和使用几乎和 C# 一模一样。

1.6.1 有返回值的函数

void name(in 参数类型 参数名, out 参数类型 参数名)
{
     函数体
}
  • void:以 void 开头,表示没有返回值。
  • name:函数的名称。
  • in:表示输入参数,由函数外部传递给函数内部,内部不会修改该参数,只会使用该参数进行计算。允许有多个。
  • out:表示输出参数,由函数内部传递给函数的调用者,在函数内部必须对该参数值进行初始化或修改。允许有多个。

注意:

  1. in 和 out 都可以省略。
  2. 虽然可以省略,但省略后就没有 in 和 out 的相关限制。
  3. 建议编写 Shader 时不要省略 in 和 out,以明确参数的传递方式,提高代码的可读性和可维护性。

1.6.2 有返回值的函数

type name(in 参数类型 参数名)
{
     函数体
     return 返回值;
}
  • type:返回值类型。
  • return:返回指定类型的数据。

注意:

  1. 可以在有返回值的函数中使用 out 参数,但不是常见做法,除非是一些自定义逻辑函数。
  2. 对于顶点/片元着色器,函数只会使用单返回值的方式进行处理。

2 顶点/片元着色器

2.1 着色器结构

Shader "Unlit/Lesson20"
{
    Properties {...}
    
    SubShader
    {
        Tags {...}
        LOD 100

        Pass
        {
            CGPROGRAM

            #pragma vertex myVert
            #pragma fragment my_frag

            // 顶点着色器函数 
            // POSITION:把模型的顶点坐标填充到输入的参数 v 当中
            // SV_POSITION:顶点着色器输出的内容是裁剪空间中的顶点坐标
            float4 myVert(float4 v:POSITION) : SV_POSITION
            {
                // mul(UNITY_MATRIX_MVP,v);
                return UnityObjectToClipPos(v); // mul是 CG 语言内置的矩阵和向量的乘法运算函数
                                                // UNITY_MATRIX_MVP 代表变换矩阵,是 Unity 内置的模型、观察、投影矩阵的集合
                                                // 新版本使用 UnityObjectToClipPos 将矩阵乘法封装起来,使用更加方便。主要目的也是坐标变换 
            }
            
            // 片元着色器函数
            // SV_Target:告诉渲染器,将用户输出颜色存储到渲染目标中,这里将输出到默认的帧缓存中
            fixed4 myFrag() : SV_Target
            {
                return fixed4(0, 1, 0, 1);
            }
            
            ENDCG
        }
    }
}

2.2 语义

​ CG 语言中提供了“语义”关键字,用于修饰函数中的传入参数和返回值。主要作用是让 Shader 知道从哪里读取数据,并把数据输出到哪里。

​ 注意:Unity 中只支持 CG 当中的部分语义。

2.2.1 应用阶段 ―> 顶点着色器

​ 应用阶段传递模型数据给顶点着色器时 Unity 支持的语义,一般在顶点着色器回调函数的传入参数中应用。

语义说明
POSITION模型空间中的顶点位置,通常是 float4 类型
NORMAL顶点法线,通常是 float3 类型
TANGENT顶点切线,通常是 float4 类型
TEXCOORDn比如 TEXCOORD0、TEXCOORD1…
该顶点的纹理坐标,通常是 float2 或者 float4 类型
TEXCOORD0 表示第一组纹理坐标,依次类推
纹理坐标:也称 UV 坐标,表示该顶点对应纹理图像上的位置
COLOR顶点颜色,通常是 fixed4 或 float4 类型

2.2.2 顶点着色器 ―> 片元着色器

​ 从顶点着色器传递数据给片元着色器时 Unity 支持的语义, 一般在顶点着色器回调函数的返回值中应用。

语义说明
SV_POSITION裁剪空间中的顶点坐标(必备)
COLOR0通常用于输出第一组顶点颜色(非必须)
COLOR1通常用于输出第二组顶点颜色(非必须)
TEXCOORD0~TEXCOORD7通常用于输出纹理坐标(非必须)

2.2.3 片元着色器

​ 片元着色器输出时 Unity 支持的常用语义,一般在片元着色器回调函数的返回值中应用。

语义说明
SV_Target输出值会存储到渲染目标中

更多语义:https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDN

2.3 多参数传递

​ 使用结构体对数据进行封装,通过对结构体中成员变量加语义的方式来定义想要获取的信息。

Shader "Unlit/Lesson20"
{
    Properties {...}
    
    SubShader
    {
        Tags {...}
        LOD 100

        Pass
        {
            CGPROGRAM

            #pragma vertex myVert
            #pragma fragment my_frag

            // 从应用阶段获取对应语义数据,用于传递给顶点着色器函数
            struct a2v
            {
                float4 vertex : POSITION; // 顶点坐标(模型空间下)
                float3 normal : NORMAL; // 顶点法线(模型空间下)
                float2 uv : TEXCOORD0; // 纹理坐标(UV 坐标)
            };

            // 从顶点着色器函数获取对应语义数据,用于传递给片元着色器函数
            struct v2f
            {
                float4 position : SV_POSITION; // 顶点坐标(裁剪空间下)
                float3 normal : NORMAL; // 顶点法线(模型空间下)
                float2 uv : TEXCOORD0; // 纹理坐标(UV 坐标)
            };

            v2f vert(a2v data)
            {
                v2f output;
                output.position = UnityObjectToClipPos(data.vertex);
                output.normal = data.normal;
                output.uv = data.uv;
                
                return output;
            }

            fixed4 frag(v2f data) : SV_Target
            {
                return fixed4(0, 1, 0, 1);
            }
            
            ENDCG
        }
    }
}

注意:

  1. 片元着色器中获取的数据基本上都由顶点着色器传递过来,所以封装的结构体需要作为顶点着色器的返回值类型。
  2. 只有顶点/片元着色器的回调函数相关参数和返回值才需要通过语义修饰,一般的自定义函数不需要语义,因为自己调用的自定义函数可以明确知道每个参数的作用。

2.4 CG 变量类型与 ShaderLab 属性

ShaderLab 属性CG 变量
Color、Vectorfloat4、half4、fixed4
Range、Float、Intfloat、half、fixed
2Dsampler2D
CubesamplerCube
3Dsampler3D
2DArraysampler2DArray

​ 在 CG 语句块中使用 ShaderLab 中声明的属性,只需声明和属性中对应类型的同名变量即可。

​ 示例:

Shader "Unlit/Lesson23"
{
    Properties
    {
        _MyInt("MyInt", Int) = 1
        _MyFloat("MyFloat", Float) = 1.0
        _MyRange("MyRange", Range(0, 1)) = 0.5
        
        _MyColor("MyColor", Color) = (1, 1, 1, 1)
        _MyVector("MyVector", Vector) = (1, 1, 1, 1)
        
        _My2D("My2D", 2D) = "white" {}
        _MyCube("MyCube", Cube) = "white" {}
        _My3D("My3D", 3D) = "white" {}
    }
    
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float _MyInt;
            float _MyFloat;
            float _MyRange;

            fixed4 _MyColor;
            float4 _MyVector;

            sampler2D _My2D;
            samplerCUBE _MyCube;
            sampler3D _My3D;

            ...
                
            ENDCG
        }
    }
}

2.5 CG 内置函数

​ Unity Shader 中的 CG 语言提供了各种用于图形编程的函数,这些函数是 CG 为封装好的逻辑,可以使用它们来编写 Unity Shader。

2.5.1 数学函数

  1. 三角

    函数说明
    sincos(float x, out s, out c)同时计算 x 的 sin 值和 cos 值,通过 s 和 c 进行返回(比分别运算快很多)
    sin(x)正弦函数
    cos(x)余弦函数
    tan(x)正切函数
    sinh(x)双曲正弦函数
    cosh(x)双曲余弦函数
    tanh(x)双曲正切函数
    asin(x)反正弦函数,输入参数范围 [-1, 1],返回 [-π/2, π/2] 区间的角度值
    acos(x)反余弦函数,输入参数范围 [-1, 1],返回 [0, π] 区间的角度值
    atan(x)反正切函数,输入参数范围 [-1, 1],返回 [-π/2, π/2] 区间的角度值
    atan2(y, x)计算 y/x 的反正切值。和 atan 功能一样,只是输入参数不同。atan(x) = atan2(x,1)
  2. 向量、矩阵

    函数说明
    cross(A, B)叉乘(注意:传入向量必须是三维向量)
    dot(A, B)点乘(注意:传入向量必须是三维向量)
    mul(M, N)计算两个矩阵相乘
    mul(M, v)计算矩阵和向量相乘
    mul(v, M)计算向量和矩阵相乘
    transpose(M)M为矩阵,计算M的转置矩阵
    determinant(m)计算矩阵的行列式因子
  3. 计算数值

    函数说明
    abs(x)返回输入参数的绝对值
    ceil(x)对输入参数向上取整
    floor(x)对输入参数向下取整
    clamp(x, a, b)"夹紧"函数
    x 小于 a,则返回 a;
    x 大于 b,则返回 b;
    否则,返回 x
    radians(x)角度转弧度
    degrees(x)弧度转角度
    max(a, b)返回最大值
    min(a, b)返回最小值
    sqrt(x)求 x 的平方根,x 必须大于 0
    pow(x, y)x 的 y 次方的值
    round(x)对 x 四舍五入
    rsqrt(x)x 的反平方根,x 必须大于 0
    lerp(a, b, f)差值函数,计算 (1-f)*a + b*f 或者 a + f*(b-a) 的值
    exp(x)计算 e 的 x 次方的值,e = 2.71828182845904523536
    exp2(x)计算 2 的 x 次方的值
    fmod(x, y)返回 x/y 的余数,y 不为 0
    frac(x)返回标量或每个矢量分量的小数部分
    frexp(x, out exp)将浮点数 x 分解为尾数和指数,即 x = m * 2 的 exp 次方,返回 m,将指数存储 exp 中
    isfinite(x)判断标量或者向量中的每个数据是否是有限数,如果是返回 true,否则返回 false
    isinf(x)判断标量或者向量中的每个数据是否是无限,如果是返回 true,否则返回 false
    isnan(x)判断标量或者向量中的每个数据是否是非数据,如果是返回 true,否则返回 false
    ldexp(x,n)计算 x*2 的 n 次方 的值
    log(x)计算 ln(x) 的值,x 必须大于 0
    log2(x)计算 log2(x 次方)的值,x 必须大于 0
    log10(x)计算 log10(x 次方)的值,x 必须大于 0
    saturate(x)如果 x 小于0,返回 0;
    如果 x 大于1,返回 1;
    否则,返回 x
    sign(x)如果 x 大于 0,返回 1;
    如果 x 小于 0,返回 -1;
    否则,返回 0
    smoothstep(min, max, x)值 x 位于 [min、max] 区间内:
    如果 x = min,返回 0;
    如果 x = max,返回 1;
    如果在两者之间,返回 -2*((x-min)/(max - min))^3 + 3* ((x - min)/(max - min))^2
    step(a, x)如果 x < a,返回 0;
    否则,返回 1
    all(x)输入参数均不为 0,则返回 true;否则返回 false。相当于逻辑与 &&
    any(x)输入参数只要有其中一个不为 0,则返回 true。相当于逻辑或
  4. 其他

    函数说明
    lit(NdotL, NdotH, m)N 表示法向量;L 表示入射光向量;H 表示半角向量;m 表示高光系数
    该函数计算环境光、散射光、镜面光的贡献,返回 4 维向量;
    x 位表示环境光贡献;y 位表示散射光贡献;z 位表示镜面光贡献;w 始终为 1
    noise(x)噪声函数,返回值始终是 0~1 之间;
    对于相同的输入,始终返回相同值,不是真正意义的随机噪声

2.5.2 几何函数

函数说明
length(v)返回一个向量的模长
normalize(v)归一化向量
distance(p1, p2)计算两点之间的距离
reflect(I, N)计算反射光方向向量,I 为入射光,N 为顶点法向量。I 是指向顶点的,I 和 N 必须被归一化,必须是 3 维向量
refract(I, N, eta)计算折射向量,I 为入射光,N 为顶点法向量,eta 为折射系数。I 是指向顶点的,I 和 N 必须被归一化,必须是 3 维向量

2.5.3 纹理函数

  1. 二维纹理

    函数说明
    tex2D(sampler2D tex, float2 s)二维纹理查询
    tex2D(sampler2D tex, float2 s, float2 dsdx, float2 dsdy)使用导数值查询二维纹理
    tex2D(sampler2D tex, float3 sz)二维纹理查询,并进行深度值比较
    tex2D(sampler2D tex, float3 sz, float2 dsdx, float2 dsdy)使用导数值查询二维纹理,并进行深度值比较
    tex2Dproj(sampler2D tex, float3 sq)二维投影纹理查询
    tex2Dproj(sampler2D tex, float4 szq)二维投影纹理查询,并进行深度值比较
  2. 立方体纹理

    函数说明
    texCUBE(samplerCUBE tex, float3 s)查询立方体纹理
    texCUBE(samplerCUBE tex, float3 s, float3 dsdx, float3 dsdy)结合导数值查询立方体纹理
    texCUBEDproj(samplerCUBE tex, float4 sq)查询立方体投影纹理,并进行深度值比较
  3. 其他纹理

    函数说明
    tex1D(sampler1D tex, float s)一维纹理查询
    tex1D(sampler1D tex, float s, float dsdx, float dsdy)使用导数值查询一维纹理
    tex1D(sampler1D tex, float2 sz)一维纹理查询,并进行深度值比较
    tex1D(sampler1D tex, float2 sz, float dsdx, float dsdy)使用导数值查询一维纹理,并进行深度值比较
    tex1Dproj(sampler1D tex, float2 sq)一维投影纹理查询
    tex1Dproj(sampler1D tex, float3 szq)一维投影纹理查询,并进行深度值比较
    texRECT(samplerRECT tex, float2 s)矩形纹理查询
    texRECT(samplerRECT tex, float2 s, float2 dsdx, float2 dsdy)使用导数值查询矩形纹理
    texRECT(samplerRECT tex, float3 sz)矩形纹理查询,并进行深度值比较
    texRECT(samplerRECT tex, float3 sz, float2 dsdx, float2 dsdy)使用导数值查询矩形纹理,并进行深度值比较
    texRECTproj(samplerRECT tex, float3 sq)矩形投影纹理查询
    texRECTproj(samplerRECT tex, float3 szq)矩形投影纹理查询,并进行深度值比较
    tex3D(sampler3D tex, float3 s)查询三维纹理
    tex3D(sampler3D tex, float3 s, float3 dsdx, float3 dsdy)结合导数值查询三维纹理
    tex3DDproj(sampler3D tex, float4 sq)查询三维投影纹理,并进行深度值比较

其他函数:https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-intrinsic-functions

2.6 CG 内置文件

​ 可以在 Unity 的安装目录中找到 CG 内置文件,在 Editor ->Data -> CGIncludes 中。

​ CG 内置文件是预定义的 Shader 文件,里面包含已经写好的 Shader 相关逻辑,可以直接使用其中的方法等内容。

  • 后缀为 cginc 的文件为 CG 语言内置文件。
  • 后缀为 glslinc 的文件为 GLSL 语言内置文件。

​ Unity 中常用的内置文件有:

  1. UnityCG.cginc:包含最常用的帮助函数、宏和结构体等。
  2. Lighting.cginc:包含各种内置光照模型。如果编写的是 Surface Shader(标准表面着色器),会自动包含进来。
  3. UnityShaderVariables.cginc:编译 UnityShader 时,会自动包含进来。包含许多内置的全局变量。
  4. HLSLSupport.cginc:编译 UnityShader 时,会自动包含进来。声明了很多用于跨平台编译的宏和定义。

2.6.1 使用 CG 内置文件

​ 通过编译指令:

#include "内置文件名.cginc"

​ 在 CG 语句块中进行引用,便可以在 CG 语言中使用其中的内容。

注意:

​ 一些常用的函数、宏、变量可以不引用,Unity 会在编译时自动识别。但是为了避免报错,建议都引用。

2.6.2 常用内容

  1. 方法

    以下内容在 UnigyCG.cginc 中。

    • float3 WorldSpaceViewDir(float4 v)

      输入一个模型空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向。

    • float3 ObjSpaceViewDir(float4 v)

      输入一个模型空间中的顶点位置,返回模型空间中从该点到摄像机的观察方向。

    • float3 WorldSpaceLightDir(float4 v)

      仅用于向前渲染中。输入一个模型空间中的顶点位置,返回世界空间中从该点到光源的光照方向。(返回值没有被归一化)

    • flaot3 ObjSpaceLightDir(float4 v)

      仅用于向前渲染中。输入一个模型空间中的顶点位置,返回模型空间中从该点到光源的光照方向。(返回值没有被归一化)

    • float3 UnityObjectToWorldNormal(float3 norm)

      把法线方向从模型空间转换到世界空间中。

    • float3 UnityObjectToWorldDir(in float3 dir)

      把方向矢量从模型空间转换到世界空间中。

    • float3 UnityWorldToObjectDir(float3 dir)

      把方向矢量从世界空间转换到模型空间中。

  2. 结构体

    以下内容在 UnigyCG.cginc 中。

    • appdata_base

      用于顶点着色器输入。

      顶点位置、顶点法线、第一组纹理坐标。

    • appdata_tan

      用于顶点着色器输入。

      顶点位置、顶点法线、顶点切线、第一组纹理坐标。

    • appdata_full

      用于顶点着色器输入。

      顶点位置、顶点法线、顶点切线、四组(或更多)纹理坐标。

    • appdata_img

      用于顶点着色器输入。

      顶点位置、第一组纹理坐标。

    • v2f_img

      用于顶点着色器输出。

      裁剪空间中的位置,纹理坐标。

  3. 变换矩阵宏

    坐标空间变换顺序:模型空间 -> 世界空间 -> 观察空间 -> 裁剪空间 -> 屏幕空间

    以下内容在 UnityShaderVariables.cginc 中。

    • UNITY_MATRIX_MVP

      当前的模型观察投影矩阵,用于将顶点/方向向量从模型空间变换到裁剪空间中。

    • UNITY_MATRIX_MV

      当前的模型*观察矩阵,用于将顶点/方向向量从模型空间变换到观察空间中。

    • UNITY_MATRIX_V

      当前的观察矩阵,用于将顶点/方向向量从世界空间变换到观察空间中。

    • UNITY_MATRIX_P

      当前的投影矩阵,用于将顶点/方向向量从观察空间变换到裁剪空间中。

    • UNITY_MATRIX_VP

      当前的观察*投影矩阵,用于将顶点/方向向量从世界空间变换到裁剪空间中。

    • UNITY_MATRIX_T_MV

      UNITY_MATRIX_MV 的转置矩阵。

    • UNITY_MATRIX_IT_MV

      UNITY_MATRIX_MV 的逆转置矩阵,用于将法线从模型空间变换到观察空间,也可用于得到 UNITY_MATRIX_MV 的逆矩阵。

    • _Object2World

      当前的模型矩阵,用于将顶点/方向矢量从模型空间变换到世界空间。

    • _World2Object

      _Object2World 的逆矩阵,用于将顶点/方向矢量从世界空间变换到模型空间。

  4. 变量

    • _Time(不用引用,直接使用即可)

      自关卡加载以来的时间,用于对着色器内的事物进行动画处理。

    • _LightColor0(向前渲染时,UnityLightingCommon.cginc;延迟渲染,UnityDeferredLibrary.cginc)

      光的颜色。

更多内容:

  1. 内置文件相关:https://docs.unity3d.com/Manual/SL-BuiltinIncludes.html
  2. 函数相关:https://docs.unity3d.com/Manual/SL-BuiltinFunctions.html
  3. 宏相关:https://docs.unity3d.com/Manual/SL-BuiltinMacros.html
  4. 变量相关:https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔗理苦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值