在上一篇 Unity Shader 入门笔记(二)中,我们了解了关于Unity Shader中顶点着色器和片元着色器如何通信和渲染,本文中我们将继续学习和了解上文提及的Unity的语义和内置包含文件。
包含文件(include file),类似于C++中头文件的一种文件。
在Unity中,他们的文件后缀是.cgnic
。在编写Shader时,我们可以使用#include指令把这些文件包含进来,我们就可以使用Unity为我们提供的变量和函数,写法如下所示:
CGPROGRAM
#include "UnityCG.cginc"
ENDCG
相关文件位置如下:
{unity 安装路径}/Data/CGIncludes/UnityCG.cginc
/Applications/Unity/Unity.app/Contents/CGIncludes/UnityCG.cginc
Unity内置包含文件都在CGIncludes文件夹中,下面介绍比较常用的几个文件:
1.1. 介绍一些 UnityGC.cginc中一些常用结构
appdata_base | 可用于顶点着色器输入 | 顶点位置、顶点法线、第一组纹理坐标 |
appdata_tan | 可用于顶点着色器输入 | 顶点位置、顶点切线、顶点法线、第一组纹理坐标 |
appdata_full | 可用于顶点着色器输入 | 顶点位置、顶点切线、顶点法线、四组(更多)组纹理坐标 |
appdata_img | 可用于顶点着色器输入 | 顶点位置、第一组纹理坐标 |
v2f_img | 可用于顶点着色器输出 | 裁剪空间中的位置、纹理坐标 |
1.2. 关于 UnityCG.cgnic 中常用的帮助函数
读者可查阅如下链接的官方文档,进行了解和学习:
1.3. 如何使用 UnityGC.cginc 的结构体和帮助函数?
上一篇文章中,我们写了一些简单的shader,并自己定义了顶点着色器输入结构,下面尝试使用#include "UnityCG.cginc"
,将a2v
修改为appdata_base
,如下所示:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "My Shader/SimpleShader03"
{
Properties{
_Color ("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0)
}
SubShader
{
Pass{
CGPROGRAM
//声明顶点着色函数 vert是顶点着色函数名字
#pragma vertex vert
//声明片元着色函数 frag是片元着色函数名字
#pragma fragment frag
#include "UnityCG.cginc"
//在CG代码中,需要定义一个属性名称都和类型匹配的变量
fixed4 _Color;
//顶点着色器的输入
// struct a2v {
// float4 vertex : POSITION; //用模型空间顶点填充vertex变量
// float3 normal : NORMAL; //用模型空间法线填充normal变量
// float4 texcoord : TEXCOORD0; //用模型空间第一套纹理坐标填充texcoord变量
// };
//顶点着色器的输出 --> 输出到片元着色器
struct v2f{
float4 pos : SV_POSITION;
fixed3 color : COLOR0;
};
// POSITION / SV_POSITION 是 CG/HLSL 的语义
v2f vert (appdata_base v)
{
v2f o;
//注意:MVP变换就是将模型空间转化到裁剪空间
o.pos = UnityObjectToClipPos(v.vertex);
//顶点法线的分量范围在[-1,1]之间
o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
return o;
}
// SV_Target 是HLSL中的系统语义,
//它等同于告诉渲染器,将用户输出的颜色存储到一个渲染目标上
//这里输出到默认的帧缓存上
fixed4 frag (v2f i) : SV_Target
{
fixed3 c = i.color;
c *= _Color.rgb;
return fixed4(c,1.0);
}
ENDCG
}
}
}
?
?
2.1. 什么是语义
语义可以让Shader知道从哪里读取数据,并且把数据输出到哪里。
在DirectX 10以后,有了一种新的语义类型,就是系统数值语义(System-value semanties)。这类语义是以SV开头的,SV代表的含义就是系统数值(System-value)。
使用SV_POSITION
语义去修饰顶点着色器的输出变量pos
,就表示pos
包含了可用于光栅化的变换后的顶点坐标,用这里语义描述的变量是不可以随便赋值的,因为流水线需要使用它们来完成特定目的。
官方文档语义说明:着色器语义 - Unity 手册
2.2. Unity中的语义总结
2.2.1. 从应用阶段传递模型数据给顶点着色器时Unity支持的语义
?
2.2.2. 从顶点着色器传递数据给片元着色器时Unity使用的常用语义
?
?
?
?
2.3. 在程序中使用语义
struct v2f{
float4 pos : SV_POSITION;
fixed3 color0 : COLOR0;
fixed4 color1 : COLOR1;
half value0 : TEXCOORD0;
float2 value1 : TEXCOORD1;
}
2.4. Shader语义差异
在某些平台上SV_POSITION
和POSITION
是等价的,但在某些平台上不等价。尽量使用下面的语义描述Shader的输入输出变量:
SV_POSITION
描述顶点着色器输出的顶点位置。SV_TARGET
描述片元着色器的输出颜色。?
3.1. 内部调试工具
具体使用参考官方链接:Frame Debugger window reference - Unity 手册
3.2. 其他调试工具
具体可以搜索一下相关工具名称和使用方法,本文不在赘述。
本文中我们了解了Unity的语义和内置包含文件,以及内置包含文件如何使用,并简单介绍了关于Unity的调试工具,接下来我们将开始学习Unity中的基本光照模型,学习如何在Unity中实现简单的局部光照效果。
最后,非常感谢您能看到这里,如果该文章对你有所帮助和启发,也欢迎您能点赞👍支持,如果有任何疑问和优化建议也非常欢迎各位大佬能够在评论区友好交流,一起学习进步。
?