众所周知,要想当游戏开发工程师,Unity中的Shader编写不得不摸,这一系列文章我将描写我的Shader学习之路,致敬冯乐乐的书Unity Shader入门精要,此篇什么是Unity Shader?希望能给后人一点方向
我们刚开始接触Unity的时候,总是会遇到材质,但是不了解材质都是什么,为什么可以在很多材质中选择,为什么有时候选择了其他材质后就不能达到我们想要的结果,为什么资源商店有那么多的材质,山川湖地,我们可以自己写材质吗,那么这篇正好可以讲明白材质是什么,和我的系列要说的UnityShader的关系,话不多说,进入正题-----
对于计算机中的每一个物体,比如一个模型,想要让他显示出来,需要很多的步骤,这么一连串的步骤叫做渲染流水线,在这些流水线中,有一些步骤是可以由开发者自己编程的,比如顶点着色器,片元着色器,所以在游戏开发中,要渲染一个模型的时候,需要写很多GPU(图形处理器)使用的代码,但是这些接近底层的代码很复杂,所以Unity的出现改善了这个情况,Unity提供了一个地方能够让开发者更加轻松的管理着色器代码以及渲染设置(如开启混合模式,深度测试,设置渲染顺序),Unity提供的这个地方就是Unity Shader
1创建材质
2创建Unity Shader,赋给创建的材质
3将材质赋给要渲染的对象
4材质面板调整Unity Shader的属性
首先,我们创建一个Unity Shader和材质,Unity Shader就是中文的着色器,材质就是中文的材质
下面是新建的材质,上面是新建的Unity Shader
点开新建材质,材质的Shader属性里面可以发现我们创建的Unity Shader
上述的着色器代码以及渲染设置(如开启混合模式,深度测试,设置渲染顺序)定义于Unity Shader,将Unity Shader拖入材质后,可以在材质中调整这些属性
新建材质很简单,那么把新建的材质用到物体上,怎么操作呢
我们可以看到这两个组件,其中Mesh Renderer可以拖入材质,这两个组件就是完成把新建的材质用到物体上任务所需要的了
Mesh Renderer详解: 点这里.
当我们新建Unity Shader的时候,发现有很多选择,这是Unity提供的模板
这是包含标准光照模型的表面着色器模板
如果着色器需要受到光照和阴影的影响,则表面着色器是您的最佳选择。表面着色器以简洁的方式使编写复杂的着色器变得容易 - 这是与 Unity 光照管线进行交互的更高级别抽象。大多数表面着色器自动支持前向和延迟光照。您可以用几行 Cg/HLSL 编写表面着色器,随后就能在此基础上自动生成更多代码。
如果您的着色器与光照没有任何关联,请不要使用表面着色器。对于后期处理效果或许多特殊效果着色器,表面着色器是次优选项,因为它们会无缘无故进行大量光照计算。
这是不包含光照的基本顶点和片元着色器
如果您的着色器不需要与光照交互,或者如果您需要无法由表面着色器处理的非常奇特的效果,则需要使用顶点和片元着色器。以这种方式编写的着色器程序是创建所需效果的最灵活方法(甚至表面着色器也会自动转换为一堆顶点和片元着色器),但这需要付出代价:必须编写更多的代码并且更难以让它与光照互动。这些着色器也是以 Cg/HLSL 编写。
这是包含各种屏幕后处理效果的着色器
与常规渲染无关的计算,对于初级不太用的上
固定函数着色器是传统的着色器语法,用于非常简单的效果。建议编写可编程的着色器,因为这样可以提供更大的灵活性。固定函数着色器完全用一种名为 ShaderLab 的语言编写,此语言类似于 Microsoft 的 .FX 文件或 NVIDIA 的 CgFX。在内部,所有固定函数着色器在导入着色器时转换为顶点和片元着色器。
着色器检视面板显示有关着色器的基本信息(主要是着色器标签), 并允许编译和检查低级编译代码。
对于表面着色器 (Surface Shader),Show generated code 按钮将显示 Unity 生成的用于处理光照和阴影的所有代码。如果确实想要 自定义生成的代码,只需将其全部复制并粘贴回原始着色器文件 并开始调整即可。
Compile and show code 按钮的弹出菜单可检查选定平台 最终编译的着色器代码(例如 Direct3D9 上的程序集,或适用于 OpenGL ES 的 低级优化 GLSL)。此功能在优化着色器性能时非常有用;通常情况下,您会想知道最后在此处生成了 多少低级指令。
生成的低级代码可用于粘贴到 GPU 着色器性能分析工具(如 AMD GPU ShaderAnalyzer 或 PVRShaderEditor)。
着色器检视面板有很多属性,这里不详细解释,后面我们写代码的时候会自己写属性,就会更理解
在着色器导入时,Unity 不会编译整个着色器。这是因为大多数着色器 内部都有很多变体,因此为所有可能的平台编译所有这些变体 将需要很长时间。实际的操作过程为:
在导入时,仅对着色器进行最低限度的处理(表面着色器生成等)。
只在需要时实际编译着色器变体。
不会在导入时执行编译 100–10000 个内部着色器的典型工作,此过程通常最终只编译少数着色器。
在播放器构建时,所有“尚未编译”的着色器变体都将被编译,因此即使 Editor 不会使用这些着色器变体,它们也会存在于游戏数据中。
但是,这确实意味着着色器可能具有在着色器导入时未检测到的 错误。例如,正在使用 Direct3D 11 运行 Editor,但如果着色器是针对 OpenGL 进行编译的, 则会出错。此外,还可能着色器的某些变体不符合着色器模型 2.0 指令限制等。如果 Editor 需要了解这些错误,它们将显示在检视面板中;但是,为了检查错误,手动为所需平台 完全编译着色器也是一种很好的做法。使用着色器检视面板 中的 Compile and show code 弹出菜单即可执行此操作。
着色器编译是使用名为 UnityShaderCompiler 的后台进程执行的,该进程由 Unity 在需要编译着色器时即时启动。可启动多个编译器进程(通常在机器中每个 CPU 核心对应一个),这样在播放器构建时就可以并行完成着色器编译。当 Editor 不编译着色器时,编译器进程不执行任何操作,也不消耗计算机资源, 所以不必担心它们。Unity Editor 退出时也将关闭这些进程。
各个着色器变体编译结果将缓存在项目中的 Library/ShaderCache 文件夹下。 这意味着 100% 相同的着色器或其代码片段将重用以前编译的结果。此外还 意味着,如果有许多经常更改的着色器,着色器缓存文件夹可能会变得 非常大。删除文件夹内容通常是安全的;只会导致重新编译着色器变体。