《Unity Shader入门精要》读书笔记04
终于从上一章爬出来了。。。
Unity 版本为 2022.3
第 5 章 开始 Unity Shader 学习之旅
绝大部分代码写在SubShader->Pass中。
一个最简单的顶点/片元着色器
1 | #prama vertex name1 |
它们告诉Unity,哪个函数包含了顶点着色器的代码,哪个函数包含了片元着色器的代码。
vert 函数
1 | float4 vert(float4 v : POSITION) : SV_POSITION { |
vert函数的输入 v 包含了这个顶点的位置,这是通过POSITION语义指定的。它的返回值是一个 float4 类型的变量,它是该顶点在裁剪空间中的位置,POSITION 和 SV_POSITION 都是CG/HLSL中的语义(semantics),它们是不可省略的,这些语义将告诉系统用户需要哪些输入值,以及用户的输出是什么。例如这里,POSITION将告诉Unity,把模型的顶点坐标填充到输入参数v中,SV_POSITION将告诉Unity,顶点着色器的输出是裁剪空间中的顶点坐标。
frag 函数
1 | fixed4 frag() : SV_Target { |
SV_Target : HLSL中的一个系统语义,它等同于告诉渲染器,把用户的输出颜色存储到一个渲染目标(rendertarget)中,这里将输出到默认的帧缓存中。
来自模型的数据
1 | // 使用一个结构体来定义顶点着色器的输入 |
结构体定义格式
1 | struct StructName { |
用结构体在 vert 和 frag 之间通信
1 | //... |
使用属性Properties
1 | Shader "Unity Shaders Book/Chapter 5/Simple Shader"{ |
Unity内置文件和变量
内置的包含文件
1 | CGPROGRAM |
它们的位置:Unity的安装路径/Data/CGIncludes
| 文件名 | 描述 |
|---|---|
| UnityCG.cginc | 包含了最常使用的帮助函数、宏和结构体等 |
| UnityShaderVariables.cginc | 在编译UnityShader时,会被自动包含进来。包含了许多内置的全局变量,如UNITY_MATRIX_MVP等 |
| Lighting.cginc | 包含了各种内置的光照模型,如果编写的SurfaceShader的话,会自动包含进来 |
| HLSLSupport.cginc | 在编译Unity Shader时,会被自动包含进来。声明了很多用于跨平台编译的宏和定义 |
- 我们可以直接使用UnityCGcginc中预定义的结构体作为顶点着色器的输入和输出。
| 名称 | 包含的变量 |
|---|---|
| appdata_base | 顶点位置、顶点法线、第一组纹理坐标 |
| appdata_tan | 顶点位置、顶点切线、顶点法线、第一组纹理坐标 |
| appdata_full | 顶点位置、顶点切线、顶点法线、四组(或更多)纹理坐标 |
| appdata_img | 顶点位置、第一组纹理坐标 |
| v2f_img | (用作输出)裁剪空间中的位置、纹理坐标 |
| 还有一些常用的帮助函数。还有很多宏。以后用到再说。 |
Unity 提供的 CG/HLSL 语义
系统数值语义(system-value semantics),以SV开头,代表系统数值(system-value)。
为了让我们的Shader有更好的跨平台性,对于这些有特殊含义的变量我们最好使用以SV开头的语义进行修饰。
Unity 支持的语义
从应用阶段传递模型数据到顶点着色器
(….省略,用到了再查,真的常用后面再整理)
Debug
1.假彩色图像(false-color image)——也就是把数据作为颜色输出
2.利用 Visual Studio——Graphics Debugger
3.帧调试器(Unity自带,Window->Analysis->Frame Debugger)可以用于查看渲染该帧时进行的各种渲染事件(event)。
渲染平台的差异
在OpenGL(OpenGLES也是)中,(0,0)点对应了屏幕的左下角,而在DirectX(Metal也是)中,(0,0)点对应了左上角。
- 当我们要使用渲染到纹理技术,把屏幕图像渲染到张渲染纹理中时,如果不采取任何措施的话,就会出现纹理翻转的情况。
除此之外还有语法和语义的差异。同样,以后遇到了再做记录。
关于Shader代码的建议
- float的精度大于half, fixed, 所以优化时可以考虑降精度。
- 如果要发布到DirectX平台上,就要使用更严格的语法。
- 不同的ShaderTarget、不同的着色器阶段,我们可使用的临时寄存器和指令数目都是不同的。 对应指令
#pragma target 2.0。 - 慎用分支和循环语句。GPU使用了不同于CPU的技术来实现分支语句,在最坏的情况下,我们花在一个分支语句的时间相当于运行了所有分支语句的时间。
一个改善方法是,尽量把计算向流水线上端移动,例如把放在片元着色器中的计算放到顶点着色器中,或者直接在CPU中进行预计算,再把结果传递Shader。 - 不要除以0。对那些除数可能为0的情况,强制截取到非0范围。
- 标题: 《Unity Shader入门精要》读书笔记04
- 作者: 铁名_IronName
- 创建于 : 2026-01-14 15:03:57
- 更新于 : 2026-01-15 15:26:30
- 链接: https://blog.ironname.top/2026/01/14/《Unity-Shader入门精要》读书笔记04/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。