阿卡内酱
阿卡内酱
发布于 2026-04-14 / 0 阅读
0
0

05.初见Unity Shader

5.2 简单顶点/片元着色器

Shader "Unity Shaders Book/Chapter 5/Simple Shader" {
    Properties {
        // 声明一个Color类型的属性
        _Color ("Color Tint", Color) = (1.0,1.0,1.0,1.0)
    }
    SubShader {
        Pass {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            // 在Cg代码中,我们需要定义一个与属性名称和类型都匹配的变量
            fixed4 _Color;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR0;
            };
            
            // float4 vert1(float4 v : POSITION) : SV_POSITION{
			//     return UnityObjectToClipPos(v.vertex);
			// }

            v2f vert(a2v v) : SV_POSITION {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed3 c = i.color;
                // 使用_Color属性来控制输出颜色
                c *= _Color.rgb;
                return fixed4(c, 1.0);
            }

            ENDCG
        }
    }
}

名词解释

  • pragma:预编译指令。上述代码中的两个pragma指令分别指定了顶点着色器和片元着色器所使用的函数名称,在进行渲染过程中这两个着色器会自动调用这两个函数。

  • 属性:在Properties语义块内可定义属性。若要在Cg代码中访问某个属性,需要在代码块内提前定义和属性相同的数据类型和名称

  • 语义:在定义结构体和函数时都要为其指定语义,语义表示这个变量的数据的输入来源或者其输出的目的。例如上述注释掉的vert1函数表示v来自当前处理顶点的坐标数据,返回值自动输入到裁剪空间的坐标值。

  • 数据类型:

    • float4(3):表示一个4维向量,在Cg中默认为列向量

    • fixed3:数据表示范围为-2.0~+2.0,可以用来表示颜色或者单位向量,一般用half来代替fixed

    • float4x4:一个4x4的矩阵,默认为行优先填入。

  • 结构体:定义的结构体,其成员变量在指定了语义后在执行过程中会自动填充。

  • 顶点着色器与片元着色器的通信:可以通过一个结构体作为媒介来通信。

表5.1 ShaderLab属性类型和Cg变量类型的匹配关系

ShaderLab属性类型

Cg变量类型

Color,Vector

float4, half4,fixed4

Range,Float

float,half,fixed

2D

sampler2D

Cube

samplerCube

3D

sampler3D

uniform关键词是Cg中修饰变量和参数的一种修饰词,它仅仅用于提供一些关于该变量的初始值是如何指定和存储的相关信息(这和其他一些图像编程接口中的uniform关键词的作用不太一样)。在Unity Shader中,uniform关键词是可以省略的。

5.3 Unity内置文件和变量

包含文件

可以像c语言那样包含进外部文件进来,后缀为cginc。例:

CGPROGRAM
// ...
#include "UnityCG.cginc"
// ...
ENDCG

本地有的包含文件位于:D:\unity\2022.3.53f1c1\Editor\Data\CGIncludes
表5.2 Unity中一些常用的包含文件

文 件 名

描 述

UnityCG.cginc

包含了最常使用的帮助函数、宏和结构体等

UnityShaderVariables.cginc

在编译Unity Shader时,会被自动包含进来。包含了许多内置的全局变量,如UNITY_MATRIX_MVP等

Lighting.cginc

包含了各种内置的光照模型,如果编写的是Surface Shader的话,会自动包含进来

HLSLSupport.cginc

在编译Unity Shader时,会被自动包含进来。声明了很多用于跨平台编译的宏和定义

表5.3 UnityCG.cginc中一些常用的结构体

名 称

描 述

包含的变量

appdata_base

可用于顶点着色器的输入

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

appdata_tan

可用于顶点着色器的输入

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

appdata_full

可用于顶点着色器的输入

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

appdata_img

可用于顶点着色器的输入

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

v2f_img

可用于顶点着色器的输出

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

表5.4 UnityCG.cginc中一些常用的帮助函数

函 数 名

描 述

float3 WorldSpaceViewDir (float4 v)

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

float3 ObjSpaceViewDir (float4 v)

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

float3 WorldSpaceLightDir (float4 v)

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

float3 ObjSpaceLightDir (float4 v)

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

float3 UnityObjectToWorldNormal (float3 norm)

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

float3 UnityObjectToWorldDir (float3 dir)

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

float3 UnityWorldToObjectDir(float3 dir)

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

5.4 Unity提供的Cg/HLSL语义

语义semantics:时一个赋给Shader输入和输出的字符串,表达了这个参数的含义,一般情况下用一个语义来描述一个变量时,这个变量到底存储了什么是无所谓的。

系统数值语义(System-value Semantics):一些具有特殊意义的语义,不能随便赋值,一般是系统用于一些渲染阶段的。以SV作为前缀,例如SV_POSITION,对于这类数据,有些平台可以不用加SV前缀,但为了跨平台性最好都加上

表5.5 从应用阶段传递模型数据给顶点着色器时Unity支持的常用语义

语 义

描 述

POSITION

模型空间中的顶点位置,通常是float4类型

NORMAL

顶点法线,通常是float3类型

TANGENT

顶点切线,通常是float4类型

TEXCOORDn ,如TEXCOORD0、TEXCOORD1

该顶点的纹理坐标,TEXCOORD0表示第一组纹理坐标,依此类推。通常是float2或float4类型

COLOR

顶点颜色,通常是fixed4或float4类型

其中TEXCOORDn 中n的数目是和Shader Model有关的,例如一般在Shader Model 2(即Unity默认编译到的Shader Model版本)和Shader Model 3中,n 等于8,而在Shader Model 4和Shader Model 5中,n 等于16。通常使用时不超过2。

表5.6 从顶点着色器传递数据给片元着色器时Unity使用的常用语义

语 义

描 述

SV_POSITION

裁剪空间中的顶点坐标,结构体中必须包含一个用该语义修饰的变量。等同于DirectX 9中的POSITION,但最好使用SV_POSITION

COLOR0

通常用于输出第一组顶点颜色,但不是必需的

COLOR1

通常用于输出第二组顶点颜色,但不是必需的

TEXCOORD0~TEXCOORD7

通常用于输出纹理坐标,但不是必需的

5.5 debug工具

  1. visual studio插件:Graphics DebuggerUnity - Manual: Debug shaders with Visual Studio

  2. Unity编辑器的Fram Debugger:Window->Analysis->Frame Debugger

5.6 不同平台渲染差异

官方文档Unity - Manual: Write HLSL for different graphics APIs

  • Shader语义

    • 使用SV_POSITION 来描述顶点着色器输出的顶点位置

    • 使用SV_Target 来描述片元着色器的输出颜色‘

5.7 注意事项

5.7.3 Shader Target

当shader内需要的运算量过大时,需要指定使用更高级的shader target。
Shader Model:决定了Shader各个特性的能力,等级越高Shader越强大。但最好根据所需要的运算力来指定最低的model。
表5.9 Unity支持的Shader Target

指 令

描 述

# pragma target 2.0

默认的Shader Target等级。相当于Direct3D 9上的Shader Model 2.0,不支持对顶点纹理的采样,不支持显式的LOD纹理采样等

# pragma target 3.0

相当于Direct3D 9上的Shader Model 3.0,支持对顶点纹理的采样等

# pragma target 4.0

相当于Direct3D 10上的Shader Model 4.0,支持几何着色器等

# pragma target 5.0

相当于Direct3D 11上的Shader Model 5.0

5.7.4 流程控制语句

流程控制语句在gpu中的消耗较大,最好遵循:

  • 分支判断语句中使用的条件变量最好是常数,即在Shader运行过程中不会发生变化;

  • 每个分支中包含的操作指令数尽可能少;

  • 分支的嵌套层数尽可能少。


评论