热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

UnityShader30:预编译指令multi_complie和shader_feature

multi_complie和shader_feature编译指令往往用于正式游戏项目的优化一、关键字与Shader变体multi_complie的用法:#pra

 

multi_complie 和 shader_feature 编译指令往往用于正式游戏项目的优化


一、关键字与Shader变体

multi_complie 的用法:

#pragma multi_compile NAMEA, NAMEB, NAMEC, …,

参考代码:

Shader "Jaihk662/ShaderVariantTest"
{Properties{_MainTex("Texture", 2D) = "white" {}//枚举宏,注意在预编译指令中,宏要大写[KeywordEnum(R,G,B)] _Color("Color", float) = 0}SubShader{Tags { "RenderType" = "Opaque" }LOD 200Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile _COLOR_R _COLOR_G _COLOR_B#pragma multi_compile __ DB_ON#include "UnityCG.cginc"struct v2f{float4 vertex: SV_POSITION;float2 uv: TEXCOORD0;};sampler2D _MainTex;float4 _MainTex_ST;v2f vert(appdata_base v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);return o;}fixed4 frag(v2f i): SV_Target{#if DB_ONreturn fixed4(1, 1, 1, 1);#elif _COLOR_Rreturn fixed4(1, 0, 0, 1);#elif _COLOR_Greturn fixed4(0, 1, 0, 1);#elif _COLOR_Breturn fixed4(0, 0, 1, 1);#elsefixed4 color = tex2D(_MainTex, i.uv);return color;#endif}ENDCG}}
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestShader: MonoBehaviour
{public Material mat;void Update(){if (Input.GetKey(KeyCode.Q))mat.EnableKeyword("DB_ON");if (Input.GetKey(KeyCode.W))mat.DisableKeyword("DB_ON");}
}

其中 NAMEA 为枚举名,一个非空的枚举名为一个全局的关键字(Keyword)

关于关键字(Keyword):


  1. 指定的第一个 keyword 默认生效
  2. 对于一条预编译指令中的内容,当然同时有且只有一个 keyword 生效
  3. 在脚本中使用 material.EnableKeyword、Shader.EnableKeyword 或 CommandBuffer.EnableShaderKeyword 来指定激活哪个关键字,需要注意的是后两个方法是全局的,当然了 Keyword 不特殊声明也是全局的
  4. 同 ③ 可以使用 .DisableKeyword 方法取消激活,如果没有被激活的回到 ①
  5. 除此之外,也可以在 Properties 中定义对应的 Enum 或者 Toggle,并在材质面板中设定好 keyword,就如下图

这样做的目的是什么?对于 #pragma multi_compile _COLOR_R _COLOR_G _COLOR_B 指令,对应的 Shader 会被编译成三个变体(Variant):一是只包含 _COLOR_R 模块代码的变体 A;二是只包含 _COLOR_G 模块代码的变体 B,三是只包含 _COLOR_B 模块代码的变体 C,这就相当于是省掉了着色器中的 if 语句,直接将所有分支全部展出来

当然了,如果一个 shader 中有多个这样的预编译指令,那么生成的变体数量会是累乘的,就像上面的示例代码就会有 2 x 3 = 6 个变体

 


二、特殊的双下划线与关键字限制

上面的代码中有下面这么一段,那么对于这第二行,__ 是什么东西呢?

#pragma multi_compile _COLOR_R _COLOR_G _COLOR_B
#pragma multi_compile __ DB_ON
#pragma shader_feature FANCY_STUFF

其实它代表着当前这一行预编译指令中,所有的关键字都不生效,可以理解为“空”,它不属于关键字,对于 #pragma multi_compile __ DB_ON,其 Shader 仍会编译成两个变体:一是不包含 DB_ON 模块代码的变体;二是包含 DB_ON 模块代码的变体,当然默认为__,即不包含 DB_ON 的变体生效


  • 全局的 Keyword 只能有256个!因此可以尽量使用 __,这样可以省掉一个关键字
  • 对于只有一个关键字的情况,它相当于是省略了前面的 __,是一种简便写法

局部的关键字:

同样能使用 #pragma multi_complie_local 的方法声明只在对应 shader 内部生效的关键字(keyword),对于局部的关键字(keyword):


  • local keyword 仍有数量限制,每个 Shader 最多只能包含64个 local Keyword
  • 只能使用局部方法 material.EnableKeyword 来指定激活
  • 如果同时声明了全局和局部 keyword,局部的优先级高

 


三、multi_complie && shader_feature

multi_complie 和 shader_feature 作用完全一样,唯一的区别是:如果使用 shader_feature,build 项目时没有用到的变体就会被删除不会打出来。这也意味着在非编辑器中运行代码 Material.EnableKeyword("B") 可能会不起作用,因为没有 Material 在使用变体 B,变体 B 没有被 build 出来,运行时也找不到变体 B,而在编辑器环境下,multi_complie 和 shader_feature 没有区别


一般来讲,对于 Properties 中定义对的 Enum 或者 Toggle 关键字,使用 shader_feature,而对于在脚本中设置的关键字,使用 multi_complie,这个很好理解


如果偏要使用 shader_feature,但又避免不了用到所有的变体,也可以通过把对应 Shader 加入到 “always included shaders” 中,这样它所有的变体都会被直接打包到游戏

 

参考文档:


  • https://docs.unity3d.com/cn/current/Manual/SL-MultipleProgramVariants.html
  • https://blogs.unity3d.com/cn/2018/05/14/stripping-scriptable-shader-variants/
  • https://docs.unity3d.com/cn/current/Manual/OptimizingShaderLoadTime.html

 


推荐阅读
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 在处理UVA11987问题时,关键在于实现并查集结构以支持删除操作。特别地,当需要删除某个节点时,如果该节点不是根节点,则处理相对简单;然而,若删除的是根节点,则需要进行额外的处理来维护集合的连通性。本文将详细介绍如何通过优化并查集算法,确保在删除根节点时仍能高效地维护数据结构的完整性和查询效率。 ... [详细]
  • 计算 n 叉树中各节点子树的叶节点数量分析 ... [详细]
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • 本文深入探讨了NDK与JNI技术在实际项目中的应用及其学习路径。通过分析工程目录结构和关键代码示例,详细介绍了如何在Android开发中高效利用NDK和JNI,实现高性能计算和跨平台功能。同时,文章还提供了从基础概念到高级实践的系统学习指南,帮助开发者快速掌握这些关键技术。 ... [详细]
  • Qt 34:深入探讨缓冲区管理、目录操作及文件系统监控技术——QBuffer、QDir与QFileSystemWatcher的应用分析
    本文深入探讨了Qt框架中QBuffer、QDir和QFileSystemWatcher三个核心类的应用。QBuffer作为缓冲区管理工具,提供了高效的数据读写功能;QDir则专注于目录操作,支持路径遍历和文件检索等任务;而QFileSystemWatcher则用于实时监控文件系统的变化,便于应用程序及时响应文件或目录的增删改操作。通过实例分析,详细解析了这三个类在实际开发中的应用场景和实现细节。 ... [详细]
  • 使用Boost.Asio进行异步数据处理的应用程序主要依赖于两个核心概念:I/O服务和I/O对象。I/O服务抽象了操作系统接口,使得异步操作能够高效地执行。I/O对象则代表了具体的网络资源,如套接字和文件描述符,通过这些对象可以实现数据的读写操作。本文详细介绍了这两个概念在Boost.Asio中的应用及其在网络编程中的重要性。 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
  • 结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法
    结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法 ... [详细]
  • 本文深入探讨了 MXOTDLL.dll 在 C# 环境中的应用与优化策略。针对近期公司从某生物技术供应商采购的指纹识别设备,该设备提供的 DLL 文件是用 C 语言编写的。为了更好地集成到现有的 C# 系统中,我们对原生的 C 语言 DLL 进行了封装,并利用 C# 的互操作性功能实现了高效调用。此外,文章还详细分析了在实际应用中可能遇到的性能瓶颈,并提出了一系列优化措施,以确保系统的稳定性和高效运行。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • BZOJ1034 详细解析与算法优化
    本文深入解析了BZOJ1034问题,并提出了优化算法。通过借鉴广义田忌赛马的贪心策略,当己方当前最弱的马优于对方最弱的马时进行匹配;同样地,若己方当前最强的马优于对方最强的马,也进行匹配。此方法在保证胜率的同时,有效提升了算法效率。 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • MongoDB Aggregates.group() 方法详解与编程实例 ... [详细]
author-avatar
幸福抉择2502901973
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有