UntiyShader(六)Unity提供的Cg/HLSL语义

目录

前言

一、什么是语义(Semantics)

系统数值语义(system-value semantics)

二、Unity支持的常用语义

1.从应用阶段传递模型数据给顶点着色器时,以下在Unity中都有特殊的含义。

2.从顶点着色器阶段到片元着色器阶段

3.片元着色器的输出语义

三、如何定义复杂的变量类型


前言

在之前的案例中我们可以看到,我们编写Shader时会用到一些语义,例如SV_POSITION、POSITION、COLOR0等。

一、什么是语义(Semantics)

语义实际上就是一个赋给Shader输入和输出的字符串,这个字符串表达了这个参数的含义。通俗来讲,这些语义可以让Shader知道从哪里读取数据,并把数据输出到哪里,它们在Cg/HLSL的Shader流水线中是不可或缺的,但需要注意的是Unity并没有支持所有的语义。

通常情况下,这些输入输出变量并不需要有特别的意义,也就是说我们可以自行决定这些变量的用途。例如在之前的代码中,顶点着色器的输出结构体中我们使用了COLOR0语义去描述color变量,color变量本身存储什么,Shader流水线并不关心。

Unity为了方便对模型数据传输,对一些语义进行了特别的含义规定。比如在顶点着色器中的输入结构a2vTEXCOORD0来描述texcoord,Unity会识别TEXCOORD0语义以把模型的第一组纹理坐标填充到texcoord中,但即便语义的名称一样,如果出现的位置不同,含义也不同。比如TEXCOORD0既可以用于描述顶点着色器的输入结构a2v,也可以用于描述输出结构v2f,但在输入结构中,TEXCOORD0有特殊的含义,即把模型的第一组纹理坐标存储到改变量中,而在输出结构体中,它修饰的变量含义就可以由我们自己决定。

系统数值语义(system-value semantics)

这类语义是以SV开头的,SV代码的含义就是系统数值。这些语义在渲染流水线中有特殊的含义。

比如在之前的代码中我们使用SV_POSITION语义去修饰顶点着色器的输出变量pos,那么就表示pos包含了可用于光栅化的变换后的顶点坐标(即齐次裁剪空间中的坐标)。用这些语义描述的变量是不能够随意赋值的,因为流水线需要使用它们来完成特定的目标。

二、Unity支持的常用语义

1.从应用阶段传递模型数据给顶点着色器时,以下在Unity中都有特殊的含义。

语义 描述
POSITION 模型空间中的顶点位置,通常是float4类型
NORMAL 顶点法线,通常是float3类型
TANGET 顶点切线,通常是float4类型
TEXCOORDn,如TEXCOORD0,TEXCOORD1 该顶点的纹理坐标,TEXCOORD0是第一组纹理坐标,依此类推,通常是float2或者float4类型
COLOR 顶点颜色,通常是float4或者fixed4类型

其中TEXCOORDn中的n的数目是和Shader Model有关的。如一般在Shader Model2(即Unity默认编译到的Shader Model版本)和Shader Model3中,n等于8;而在Shader Model4Shader Model5中,n等于16。通常情况下,一个模型的纹理坐标组数一般不超过2,即我们往往使用TEXCOORD0或者TEXCOORD1

2.从顶点着色器阶段到片元着色器阶段

语义 描述
SV_POSITION 裁剪空间中的顶点坐标,结构体中必须包含一个用该语义修饰的变量。等同于DirextX9中的POSITION,但最好使用SV_POSITION
COLOR0 通常用于输出第一组顶点颜色,但不是必需的
COLOR1 通常用于输出第二组顶点颜色,但不是必需的
TEXCOORD0~TEXCOORD7 通常用于输出纹理坐标,但不是必需的

在以上语义中,除了SV_POSITION是由特别的含义外,其他语义对变量的含义没有明确要求,也就是说我们可以存储任意值到这些语义描述的变量值,通常如果我们需要把一些自定义的数据从顶点着色器传递给片元着色器,一般选用TEXCOORD0等。

3.片元着色器的输出语义

语义 描述
SV_Target 输出值将会存储到渲染目标(render target)中,等同于DirextX9中的COLOR语义,但最好使用SV_Target

三、如何定义复杂的变量类型

上面的语义绝大部分用于描述标量或者矢量类型(如fixed2、float、float4、fixed4等)

以下代码给出了一个使用语义来修饰不同类型变量的例子: 

struct v2f{

        float4 pos: SV_POSITION;

        fixed3 color0: COLOR0;

        fixed4 color1:COLOR1;

        half value0:TEXCOORD0;

        float2 value1:TEXCOORD1;

};

一个语义可以使用的寄存器只能处理4个浮点值(float),因此如果我们想要定义矩阵类型(如float3X4、float4X4等变量)就需要使用更多的空间。

一种方法是把这些变量拆分成多个变量(如float4X4的矩阵类型我们可以拆分4分float类型的变量,每个变量存储了矩阵的一行数据) 

你可能感兴趣的:(UnityShader入门学习,unity,图形渲染,着色器)