前面介绍了如何编写一个着色器。要实际创建该着色器的排列组合,它就必须在 vForge 中设置。
排列组合着色器和普通着色器的唯一差别在于前者包含 $ifdef / $endif 代码,后者没有。 只需在着色器中插入这些排列组合预处理器指令,就能将着色器转变成可以生成排列组合的着色器。 当您保存着色器库时,vForge 会检查着色器代码,以黄色图标标出这些着色器,而其他着色器的图标为蓝色。 使用排列组合技术的着色器无法被分配给非排列组合技术。
注:一旦您在着色器中使用排列组合指令,着色器编译器就不再直接编译该着色器。 该着色器本身将被忽略,只有它所生成的排列组合会被编译。
排列组合技术
在 Vision 引擎中,着色器库由
效果构成,效果包含
技术,技术则引用着色器。 要生成着色器的排列组合,您可以使用一个新要素,即
排列组合技术。 排列组合技术引用一个着色器。 该着色器在其代码中使用排列组合变量。
创建一个排列组合技术后,将着色器拖拽到该技术中,或右键单击技术并选择”Set Shader”(设置着色器),即可设置要使用的着色器。 接下来,该技术需要一份配置脚本,定义为该技术创建排列组合的
确切方式。 为此,首先在树状图中选中该排列组合技术。 “着色器属性”窗口会显示该技术的设置。
PermutationConfig 属性可指定配置文件(一个 Lua 脚本)。 点击 … 图标选择一个现有的脚本或创建新脚本。
排列组合配置脚本
创建新配置脚本时,其中包含一些默认代码以帮助您上手。
-- *** Vision Shader-Permutation Config-File *** -- Functions to add Permutation-Variables and their valid Values: -- AddPermutationBool ("VAR_NAME"); -- AddPermutationBoolGroup ("VAR_NAME1", "VAR_NAME2", "VAR_NAME3", ...); -- AddPermutationInt ("VAR_NAME", int1, int2, int3, ...); -- AddPermutationConst ("VAR_NAME", true/false); -- AddPermutationConst ("VAR_NAME", int); -- AddPermutationConstWithIncTag ("VAR_NAME", true/false); -- AddPermutationConstWithIncTag ("VAR_NAME", int); -- The following global variables are available: -- EffectName -- TechniqueName -- The following Permutation-Variables were extracted from the Shader: -- AddPermutationBool/Int/Const ("PERM_VAR"); -- Filtering-Function to remove unnecessary permutations: function IsPermutationSupported (PermutationValues, Platform) --if (PermutationValues["VAR_NAME"] > some_value) and (Platform == DX9 / DX11 / XBOX360 / PS3 / PSP2 / GLES2) then -- return false; --end --if (PermutationValues["VAR_NAME"] ~= some_value) and/or (PermutationValues["VAR_NAME"] == some_other_value) then -- return false; --end return true; end
vForge 甚至会解析当前被排列组合技术使用的着色器,并自动插入代码,对辨识出的排列组合变量进行配置。 正如您在上面的示例中所见,vForge 会辨识出着色器使用了
PERM_VAR 变量,并为您添加一些代码,使其正常起效并运行得更快。
该脚本已经记录了排列组合系统具有的所有功能。 该脚本为 Lua 脚本,所以使用正常Lua 语法。
这些脚本中最重要的部分是调用
AddPermutation…。 通过这些调用,您可以让着色器编译器了解所有排列组合变量,以及它们应具有的类型和值。
AddPermutationBool 添加一个布尔排列组合变量。 这些变量使用 true 和 false 值。
AddPermutationInt 添加一个整数排列组合变量。 您必须指定所有要获取的值。
AddPermutationConst 添加一个变量,但将其设为某个常数值,可以是 true/false,也可以是单个整数值。 该排列组合变量不会被添加到包含标记列表中。
AddPermutationConstAndIncTag 该排列组合变量会被添加到包含标记列表中(如果为 true(布尔)或任意整数值),除此之外和”AddPermutationConst”相同。
AddPermutationBoolGroup 添加多个布尔排列组合变量,并设置限定,其中只能有一个为 true。
注:您可以添加比着色器使用的排列组合变量更多的排列组合变量。 着色器编译器会生成更多排列组合,但会检测出这些不必要的排列组合的着色器代码是重复的,并将这些排列组合转为对同一着色器的引用。
脚本还包含过滤函数
IsPermutationSupported。 该函数可过滤掉不被特定硬件支持或无意义的排列组合。
该函数带有
PermutationValues 参数,这是一份表格,表格中,每个排列组合变量各有一个值。 此外,函数还带有一个参数,描述当前生成的排列组合用于哪种平台。 然后函数检查具体配置,判断脚本是否被支持,并返回 true 或 false 结果。
例如,您有一个支持法线贴图和视差贴图的着色器,而视差贴图必须在启用法线贴图的前提下才能执行。 因此,启用视差贴图但禁用法线贴图的排列组合是无用的。 IsPermutationSupported 可过滤掉这一配置,从而加快编译速度,也有可能减少着色器库的内存占用。
另一用途是过滤掉某些平台无法运行的特定排列组合。 例如,某些主机无法执行 PC 上可以执行的复杂着色器。 一个着色器效果可能有若干排列组合,其细节从非常简单一直到极度复杂,但不能为这些主机编译细节度极高的排列组合,因为主机无法渲染。
如果没有
IsPermutationSupported,所有排列组合都会被创建,没有一种会被弃用。
该脚本还传递了”EffectName”和”TechniqueName”变量,其中包含脚本当前执行的效果和技术的名称。 通过这些变量可在不同技术中使用相同的脚本,不过代码还是会略有不同。
AddPermutationBool ("NORMALMAP"); if (TechniqueName == "MSAA") then AddPermutationInt ("MSAA_LEVEL", 2, 3, 4); else AddPermutationConst ("MSAA_LEVEL", 1); end
创建和验证排列组合
当您有了一个排列组合技术,其中具备排列组合着色器和有效的配置脚本,您只需保存(也就意味着编译)着色器库即可生成排列组合。
有若干功能可帮助您判断排列组合是否会按配置意图正确生成。 首先,您可以轻易地显示一种技术所生成的配置:
对话框会显示将生成哪些排列组合、如何生成,以及其中是否有任何重复(即排列组合的代码完全相同)。 进一步展开节点,您甚至可以检查着色器将被生成的代码。 而且,如果配置脚本或着色器中有任何错误,对话框会向您提示。
当您编译着色器库时,着色器日志会显示大量信息,例如哪些排列组合被生成、哪些配置被使用,等等。 该日志通常仅在着色器编译失败时显示。 但您可以在着色器勾选项菜单中勾选
“Always Show Log”(始终显示日志),确保日志始终被显示:
此外,您还可以勾选“Show Auto-Generated Shaders / Techniques”(显示自动生成的着色器 / 技术)选项。 这样一来,从排列组合中生成的所有技术和着色器都会在 vForge 中显示。 有了这些信息,您可以非常轻松地检查究竟有多少技术被创建、它们有哪些设置(例如包含标记、目标平台、着色器模型、流蒙版等)。
注:您不能编辑自动生成的着色器和技术。 每当着色器库被编译时,它们都会被重新创建,所以一切手动更改都会丢失。
注:目前,在着色器库被编译后,vForge 不会更新 GUI 来显示自动生成了哪些着色器 / 技术。 要看到实时当前状态,您需要关闭着色器库并重新打开。 这一局限将在以后的版本中修正。