目录 |
1 自定义不受光着色器 1.1 创建一个着色器 1.2 HLSL 1.3 转置矩阵 1.4 常量缓冲区 1.5 核心库 1.6 编译目标级别 1.7 目录结构 2 动态批处理 2.1 启用合批 2.2 颜色 2.3 可选合批 3 GPU实例 3.1 可选实例化 3.2 材质支持 3.3 着色器支持 3.4 很多颜色 3.5 逐实例颜色 |
本文重点:
1、写一个HLSL着色器
2、定义常量缓冲区
3、使用渲染管线的核心库
4、支持动态批处理和GPU实例
这是涵盖Unity的可脚本化渲染管线的教程系列的第二部分。关于如何使用HLSL创建着色器并通过在单个绘制调用中将它们批处理来有效地渲染多个对象的方法。
本教程使用Unity 2019.1.2f1制作。
本教程是CatLikeCoding系列的一部分,原文地址见文章底部。“原创”标识意为原创翻译而非原创教程。
(256个球 1个DrawCall)
1 自定义不受光着色器
之前我们使用默认的不受光着色器来测试管线,但是要充分利用非正常的自定义管线,则需要创建自定义着色器才能使用它。因此,我们将创建自己的着色器,以替换Unity的默认Unlit着色器。
1.1 创建一个着色器
可以通过“Assets/ Create / Shader ”菜单中的选项之一创建着色器资产。Unlit Shader最合适,但是我们将通过从创建的着色器文件中删除所有默认代码来重新开始。将资产命名为Unlit。
(Unlit着色器资产)
着色器文件的基本原理在“渲染2,着色器基础知识”中进行了说明。如果你不熟悉编写着色器,请阅读一下,以便了解基本知识。要获得可用的着色器,最低要求是定义一个包含“ Properties ”块的Shader 块以及一个内部带有“Pass ”块的SubShader块。Unity会将其变成默认的白色Unlit着色器。在Shader关键字之后是一个字符串,该字符串将在材质的shader下拉菜单中使用。我们使用“My Pipeline/Unlit ”。
调整Unlit不透明材质,使其使用我们的新着色器,如果尚未着色,则将其变为白色。
(自定义着色器 不受光不透明材质)
1.2 HLSL
要编写自己的着色器,我们必须在其Pass块中放入一个程序。Unity支持GLSL或HLSL程序。虽然GLSL用于默认着色器以及“渲染2,着色器基础知识”(Shader Fundamentals),但Unity的新渲染管线着色器使用HLSL,因此我们也将其用于管线。这意味着我们必须将所有代码放在HLSLPROGRAM和ENDHLSL语句之间。
GLSL和HLSL程序有什么区别?
二者在Unity上实际上使用了相同的语法,并需要按照每个构建目标转换为适当的着色器代码。最大的不同是GLSL程序默认包含一些代码。HLSL程序不会隐式执行任何操作,要求我们明确包含任何需要的内容。这很好,因为旧的GLSL包含文件受旧的和过时的代码影响。我们将依靠较新的HLSL包含文件。
至少,Unity着色器需要一个顶点程序和一个片段程序函数,每个函数均使用pragma编译器指令定义。我们将对顶点函数使用UnlitPassVertex,对其他函数使用UnlitPassFragment。但是,我们不会将这些功能的代码直接放入着色器文件中。相反,我们将HLSL代码放在一个单独的包含文件中,我们也将其命名为Unlit,但带有hlsl扩展名。将其放在Unlit.shader所在的文件夹中,然后在pragma指令之后将其包括在HLSL程序中。
不过,Unity没有用于创建HLSL包含文件资产的便捷菜单项。你必须自己创建它,例如,复制Unlit.shader文件,将其文件扩展名更改为hlsl,然后从其中删除着色器代码。
(不受光的HLSL包含文件资产)
在包含文件内部,从包含保护开始,以防止在文件被包含一次以上的情况下导致代码重复。即使永远不会发生这种情况,但对每个包含文件都执行此操作是个好习惯。
至少,我们必须知道顶点程序中的顶点位置,该程序必须输出均匀的裁剪空间位置。因此,我们将为顶点程序定义一个输入和一个输出结构,它们都具有一个float4位置。
接下来,我们将定义顶点程序函数UnlitPassVertex。现在,直接使用对象空间顶点位置作为剪辑空间位置。这是不正确的,但是是获取编译着色器的最快方法。稍后我们将添加正确的空间转换。
现在保留默认的白色,因此我们的片段程序函数可以简单地将1作为float4返回。它接收插值顶点输出作为输入,因此即使我们不使用它,也将其添加为参数。