【Unity Shader入门精要 第5章】开始 Unity Shader 学习之旅

1. shaderLab语义

在之前的代码中,经常会看到类似POSITION 、SV_POSITION之类的东西,这些都属于shaderLab的语义。简单来讲,这类语义的作用就是用来通知Unity某个变量(或参数、输出)是干什么用的,可以以此为依据确定数据的来源和去处,这样引擎就知道需要用什么数据对相应的变量进行填充或将相应的数据填充到哪里。

如果按照固定程度来理解,大概可以分成以下三类:

  • 以SV_开头的语义,表示在渲染流水线中有特定的含义,一般用于将输出数据填充到固定的位置,如SV_Target语义表示输出填充到当前渲染的目标缓冲区(颜色缓冲区或Render Texture),且在渲染流水线的对应阶段要求必须包含相应的SV语义
  • 用于接收特定输入的语义,这类语义一般用于在渲染流水线的特定阶段接收特定数据,Unity可以根据这类语义从对应的组件(或位置)取出数据填充到相应的变量中,如在顶点着色器中用POSITION语义接收模型空间下的顶点位置
  • 除了接收特定输入外,还可以用来向后续渲染流程传递自定义数据的语义。由于我们可能用这些变量进行传值,所以这类语义在流水线的不同阶段内可能存储的值的意义不同。如COLOR0 、TEXCOORDn等

顶点着色器输入常用语义

语义 说明
POSITION 模型空间中的顶点坐标
NORMAL 模型空间中当前顶点的法向量
TANGENT 模型空间中当前顶点的切向量
TEXCOORDn 当前顶点对应第n张纹理的纹理坐标
COLOR 当前顶点颜色

顶点着色器输出常用语义

语义 说明
SV_POSITION 顶点在齐次裁剪空间中的坐标,顶点着色器的输出中必须要包含一个该语义的数据
COLOR0 一般用于向后续阶段传递自定义数据
COLOR1 一般用于向后续阶段传递自定义数据
TEXCOORDn 纹理坐标,也可用于向后续阶段传递自定义数据

片元着色器输出常用语义

语义 说明
SV_Taget 输出颜色填充到当前目标颜色缓冲区,片元着色器输出必须包含一个该语义的数据

2. 定义结构

在Unity Shader中可以使用自定义的数据结构
定义和使用都在CG代码段中

定义方式:

struct 结构名
{
	类型 变量名 :语义;
	...
}

struct v2f
{
	float4 color :COLOR0;
}

使用方式:

结构名 变量名;

如:

v2f o;
o.color = (1,1,1,1);

2. 使用顶点着色器

顶点着色器的定义位置在CG代码段中

定义方式为:

#pragma vertex 顶点着色器方法名

如:

#pragma vertex vert

顶点着色器方法结构为;

返回类型 方法名(输入类型 输入参数 : 输入语义) : 输出语义

如:

float4 vert(float4 position :POSITION) : SV_POSITION

如果返回类型为自定义结构,则不需要再在方法后面加输出语义(因为输出自定义结构中的字段已经加了语义),同理,如果输入类型为自定义结构,则输入参数也不需要指定输入语义。

如:

v2f vert(a2v input)

注意,顶点着色器的输出必须包含一个SV_POSITION语义的数据,如果输出为自定义结构,则该结构内必须包含一个SV_POSITION语义的变量

3. 使用片元着色器

与顶点着色器大体相同,区别在于:

  • 定义片元着色器方法时用fragment,如:#pragma fragment frag
  • 片元着色器的输出必须包含SV_Target语义的数据

5. 使用变量

在Unity Shader中也可以使用自定义的变量,在使用前需要先对变量进行声明
声明变量的位置在CG代码段中
声明变量的方式为;

变量类型 变量名;

如:

float fixValue;

如果需要使用在Properties中定义的属性,则需要声明与该属性同名的变量,如:

Properties
 {
 	_texValue("TexValue", 2D) = "White"{}
 }

...

CGPROGRAM
...
sampler2D _texValue;
...
ENDCG

另外我们看到,在Properties中,定义的属性类型为2D,但在声明变量的时候,声明的变量类型为sampler2D。这是因为ShaderLab中对于属性类型的划分和CG代码中对于变量类型的划分并不是一致的,一个类型的属性在CG代码中可能对应多个变量类型,但在声明变量的时候,必须要使用可以被映射到类型

映射关系:

属性类型 变量类型
Color Vector float4 half4 fixed4
Range Float float half fixed
2D sampler2D
3D sampler3D
Cube samplerCube

6. 包含文件

Unity提供一些后缀名为“.cginc”的include文件
类似于头文件,通过引用这些include文件,可以使用其中提供的变量或方法
引用位置在CG代码段中

引用方式:

#include "文件名.cginc"

如:

#include "UnityCG.cginc"

UnityCG.cginc是最常用的include文件,其中包含了前文提到的UNITY_MATRIX_MVP等常用变量,同时也提供了许多常用的变换方法

方法 返回类型 方法说明
WorldSpaceLightDir(float4 v) float3 输入一个模型空间下的坐标,返回世界空间下该位置的光源方向
ObjSpaceLightDir(float4 v) float3 输入一个模型空间下的坐标,返回模型空间下该位置的光源方向
WorldSpaceViewDir(float4 v) float3 输入一个模型空间下的坐标,返回世界空间下该位置的视线方向
ObjSpaceViewDir(float4 v) float3 输入一个模型空间下的坐标,返回模型空间下该位置的视线方向
方法 返回类型 方法说明
UnityObjectToWorldNormal(float3 normal) float3 将法线从模型空间转换到世界空间
UnityObjectToWorldDir(float3 dir) float3 将普通向量从模型空间转换到世界空间
UnityWorldToObjectDir(float3 dir) float3 将普通向量从世界空间转换到模型空间
方法 返回类型 方法说明
UnityWorldSpaceLightDir(float4 v) float3 输入一个世界空间下的位置,返回世界空间下该位置的光源方向
UnityWorldSpaceViewDir(float4 v) float3 输入一个世界空间下的位置,返回世界空间下该位置的视线方向

注意:以上返回都是未经过归一化的,需要在使用时根据实际情况自己手动进行归一化。

最近更新

  1. TCP协议是安全的吗?

    2024-05-10 00:24:05       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-10 00:24:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-10 00:24:05       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-10 00:24:05       20 阅读

热门阅读

  1. 深度学习学习日记5.8

    2024-05-10 00:24:05       12 阅读
  2. 华为开启telnet两种方式

    2024-05-10 00:24:05       16 阅读
  3. 基于picklerpc的pytorch单算子测试[单算子远程测试]

    2024-05-10 00:24:05       15 阅读
  4. Scala基础学习-循环

    2024-05-10 00:24:05       9 阅读
  5. redis之集群

    2024-05-10 00:24:05       10 阅读
  6. 【QEMU系统分析之实例篇(十八)】

    2024-05-10 00:24:05       13 阅读
  7. vue 钩子函数updated什么时候触发

    2024-05-10 00:24:05       12 阅读