Unity Shader开发-着色器变体(2)-定义着色器变体

一.定义着色器变体

定义一个着色器变体(Shader Variant)从概念和实现上讲,主要包括以下几个核心部分

1.使用预编译指令来声明变体关键字

关键字是驱动变体生成的“开关”。它们是简单的字符串标识符,用于在 Shader 代码中标记不同的功能路径。

以multi_compile类型为例在ShaderLab中声明自定义变体关键字:

#pragma multi_compile _ _CustomKeyWord

这里用到了关键字的组合写法(下划线+自定义关键字名),默认会使用第一个变体(这里的 _代表的是 默认状态或无关键字激活的状态

(*)使用下划线组合写法的好处

清晰性:它明确指出了当该组功能都未开启时的 Shader 行为。这使得 Shader 代码更易读、更易于理解。

智能裁剪:对于 shader_feature,Unity 在构建游戏时会执行 Shader Stripping(着色器裁剪)。如果你的项目中,没有任何一个材质勾选了“开启功能 A”,那么与 MY_FEATURE_ON 对应的变体就不会被编译和打包。但由于有 _ 的存在,默认的、不带该功能的变体始终会被包含(只要这个 Shader 被使用了)。

优化包体:这意味着你不需要为每个可选功能都强制打包“开启”和“关闭”两个版本。如果“开启”版本根本没用,它就不会被打包,从而节省了存储空间。

注意:Unity有变体数量的限制

(*)使用multicompile时可以不明确使用 _

隐含的默认状态:当 multi_compile 列表中没有 _ 且没有其他关键字被激活时,Unity 仍然会生成一个变体,这个变体是 没有任何该 multi_compile 行中关键字定义的。这其实就等同于“默认”或“无宏定义”的状态。但如果使用了 _ ,那么监视器面板里默认显示为未激活状态。

总结:使用下划线可以节省变体数量

(*)multi_compile与shader_feature的区别

1.概述

#pragma multi_compile指令会强制编译所有可能的关键字组合对应的 Shader 变体,无论这些变体是否在你的项目中被实际使用。

#pragma shader_feature指令会按需编译 Shader 变体,它只会编译和包含那些在你的项目中被 材质实际使用 的关键字组合对应的变体。

2.区别

功能独立:它们各自执行的任务是独立的。shader_feature 的核心是裁剪(stripping),而 multi_compile 的核心是强制编译所有变体。一个不能替代另一个的功能。

目的不同

shader_feature 主要服务于优化构建包体大小和编译时间,针对的是那些通过材质属性控制的“可选”功能。

multi_compile 主要服务于保证运行时功能的完整性,针对的是那些引擎内部控制的“必需”功能。

2.静态分支代码块

在 Shader 源代码内部,需要使用 条件编译宏(#ifdef / #ifndef / #else 来包裹那些受关键字控制的代码逻辑。这些宏在编译时根据关键字的激活状态,决定哪些代码会被包含在最终的变体中,哪些会被剔除.

一般在顶点或片元着色器中常使用如下格式分别书写变体分支的逻辑:

   #ifdef _CustomKeyword_ONxxxxxxxxxxx;#elsexxxxxxxxxxx;#endif

3.关键字与材质属性的关联(可选,但常用)

为了方便美术师和设计师在 Unity 编辑器中控制这些变体,通常需要将 Shader 关键字与材质的 Properties 块中的属性 关联起来。这通过使用像 [Toggle][KeywordEnum] 这样的属性修饰符来实现。

变体开关的实现
1.ShaderLab属性块

可以发现在Property中命名相同的属性会指向ShaderLab中的同一变体关键字。

注意命名的匹配规则

SubShader中的关键字命名:(全大写)自定义关键字名"+" _ON"

  #pragma shader_feature _CustomKeyword_ON

Proprty中声明的属性名命名:(大小写可混搭,但要与SubSahder中关键字的字符组成保持一致)自定义关键字名

  [Toggle]_CustomKeyword_ON ("Toggle MyOn", Float) = 1

另外,如果你使用不同形式(如[Toggle]和[MaterialToggle])定义了属性名完全相同的变量开关,在监视器面板中,它们将同时切换状态。

2.C#代码

1.单个材质实例

(1)启用关键字:Material.EnableKeyword(string keyword)

作用: 激活此 Material 实例上 Shader 的特定关键字

(2)禁用关键字:Material.DisableKeyword(string keyword)

作用: 禁用此 Material 实例上 Shader 的特定关键字。

(3)检查关键字状态:Material.IsKeywordEnabled(string keyword)

作用: 检查此 Material 实例上 Shader 的某个关键字是否处于激活状态。

2.全局材质

(1)启用关键字:Shader.EnableKeyword(string keyword)

作用: 激活一个全局着色器关键字。一旦激活,所有使用该关键字的 Shader 都会切换到对应的变体(如果该变体存在)。

(2)禁用关键字:Shader.DisableKeyword(string keyword)

作用: 禁用一个全局着色器关键字。

(3)检查关键字状态:Shader.IsKeywordEnabled(string keyword)

作用: 检查一个全局着色器关键字当前是否处于激活状态。

(4)重置所有全局关键字:Shader.DisableAllKeywords()

作用: 禁用所有当前激活的全局着色器关键字。这是一个比较少用的操作,因为它会影响所有 Shader 的行为。

二.着色器变体的限制

Unity中的着色器变体也存在着一些限制。

1.变体数量限制与关键字的关系

Unity 的变体数量限制主要体现在 关键字数量的限制 上,而不是直接的“变体”数量限制。这是因为每一个变体都是由一套激活的关键字组合来定义的。

(1)全局关键字限制:

Unity 对项目中所有着色器使用的全局关键字总数有一个限制。这个限制是 256 个。Unity 引擎自身也会使用大约 60 多个内部关键字(如用于光照、阴影、雾效等),这会进一步减少你可以使用的自定义关键字数量。无论是 multi_compile 还是 shader_feature 定义的关键字,只要它们是全局的(即没有使用 _local 后缀),都会计入这 256 个全局关键字的限制。

(2)局部关键字限制(Local Keywords):

从 Unity 2019.1 版本开始,引入了 局部关键字 的概念,通过 #pragma shader_feature_local#pragma multi_compile_local 来声明。每个独立的 Shader 文件可以有最多 64 个独特的局部关键字

局部关键字不计入全局关键字的 256 个限制。这是解决全局关键字限制的一种重要方式,尤其适用于那些只在该特定 Shader 内部使用的功能。注意:局部关键字不能与 Shader.EnableKeywordCommandBuffer.EnableShaderKeyword 等全局关键字 API 一起使用。

2.变体爆炸 (Shader Variant Explosion)

虽然有关键字数量的限制,但更直接的问题是 “变体爆炸”。即使你没有达到关键字数量的硬性限制,但如果你使用了过多的 multi_compile 指令,或者在shader_feature中定义了太多未优化的组合,仍然会导致天文数字的变体数量:

变体数量是关键字组合的乘积。 例如,如果你有 10 个multi_compile 指令,每个指令定义了两个关键字,那么总的变体数量可能是 210=1024 个。如果其中一些是三个或更多关键字的组合,这个数字会呈指数级增长。

本篇完

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87895.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql server耗时模拟

REATE PROCEDURE SimulateDelay AS BEGINPRINT 开始耗时操作...;-- 模拟等待 5 秒WAITFOR DELAY 00:00:05;PRINT 耗时操作完成。; END 方法二:使用忙循环(不推荐,CPU 占用高) CREATE PROCEDURE SimulateBusyLoop AS BEGINDECLARE start DATETIME GETDAT…

Zookeeper的典型应用场景?

大家好,我是锋哥。今天分享关于【Zookeeper的典型应用场景?】面试题。希望对大家有帮助; Zookeeper的典型应用场景? 超硬核AI学习资料,现在永久免费了! Zookeeper 是一个分布式协调服务,广泛应用于需要高可用性、分…

STM32F103_LL库+寄存器学习笔记12.3 - 串口DMA高效收发实战3:支持多实例化的版本

导言 《STM32F103_LL库寄存器学习笔记12.2 - 串口DMA高效收发实战2:进一步提高串口接收的效率》基于上一个版本,进一步提升代码的模块化水平,支持多实例化。 如上所示,收发大量的数据,没有丢包。 项目地址&#xff1a…

跨平台的重构版Notepad++文本编辑器

跨平台 Notepad 替代方案 Notepad 是 Windows 平台上的流行文本编辑器,但其原生版本不支持跨平台。以下是功能相似且支持多平台的替代工具: Notepadqq(Linux/macOS/Windows) Notepadqq 是 Notepad 的开源跨平台版本&#xff0c…

意法STM32F103C8T6 单片机ARM Cortex-M3 国民MCU 电机控制到物联网专用

STM32F103C8T6 单片机全面解析 1. 产品定位 STM32F103C8T6 是意法半导体(ST)推出的 经典ARM Cortex-M3内核单片机,采用 LQFP48封装,以 高性能、丰富外设和超高性价比 成为嵌入式开发领域的"国民MCU"。 2. 核心功能特…

Sui 技术如何助力 Claynosaurz 成功推出 Popkins NFT

像 Claynosaurz 这样的品牌利用 Sui 推动链上创新的边界,展示了 Web3 如何结合互动娱乐并带来独特全新的体验。Claynosaurz 最近在 Sui 上推出的 Popkins NFT 系列及其大型抽奖活动,不仅在社区参与度上取得了成功,也有力地展示了 Sui 独特的技…

OpenCV CUDA模块设备层-----反正弦运算函数asin()

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 对一个 uchar 类型的像素值(范围 [0, 255]),先归一化到浮点范围 [0.0, 1.0],然后计算其反正弦值 …

PixiJS 中 HTMLText 富文本渲染问题探究与优化思考​

起因 在使用 PixiJS 进行富文本渲染开发过程中,遭遇 HTMLText 组件处理中文字体加载时出现显著卡顿现象。针对此问题,在开源社区提交 issue 并附上相关技术细节与运行表现,期望获得解决方案。 提issues 从 issue 反馈内容来看,项目…

五、Redis的IO模型

简介 在谈及Redis为什么快的时候,很多人都只能回答redis是基于内存,所以快。但他们往往不知道,决定redis快的因素,还有它的IO模型-Reactor模型。谈及Redis的IO模型之前,先补充一下IO模型的基础知识。 IO模型演化 1.堵塞…

Cesium、ThreeWebGL详解(二)渲染引擎向GPU传数据、性能优化、引擎对比

下面从 API 定位、坐标体系、性能表现、面试常问点几个维度详细对比 Cesium、Three.js 与原生 WebGL 的绘制差异。 🧭 1. API 定位与典型应用 Cesium 聚焦全地球 GIS 场景,支持地形、影像、时空动态等地理信息功能,是专业级地图应用首选。 T…

单点登录(SSO)系统

设计一个 Java 单点登录(SSO)系统需要解决跨系统认证和会话共享问题。以下是核心设计和实现方案,包含关键组件和代码示例: 一、核心概念 认证中心 (Auth Center):中央身份验证服务令牌 (Token):用户身份凭…

《信息技术》科技核心期刊推荐

【科研必看】《信息技术》——科技核心期刊,助力你发表高影响力论文! 如果你是一位科研工作者、学者或者在校学生,正在为发表论文而努力,那么《信息技术》期刊无疑是你不可错过的选择!这本期刊以其卓越的学术影响力&am…

界面组件DevExpress WPF中文教程:Grid - 如何遍历节点?

DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

2D写实交互数字人:让AI形象拥有“真人温度“的技术革命

在人工智能技术日新月异的今天,数字人已不再是科幻电影中的概念,而是逐步渗透到我们日常生活的各个领域。然而,市场上大多数数字人产品仍停留在"能说会动"的初级阶段,缺乏真正的情感交互能力,这种"机械…

2025 年拓客系统排行榜

在数字化营销时代,拓客系统成为企业获取客户资源、提升销售效率的关键工具。以下为您盘点 2025 年表现出色的中文名字拓客系统,其中 微拓客 凭借强大功能脱颖而出,成为众多从业者的首选。 一、微拓客:精准拓客的全能王者 微拓客堪…

TikTok 矩阵如何快速涨粉

在社交媒体的广袤天地里,TikTok 以其强大的影响力和庞大的用户基础,成为众多创作者和品牌竞相角逐的舞台。构建 TikTok 矩阵,是扩大影响力、实现快速涨粉的有效策略。那么,究竟如何让 TikTok 矩阵快速涨粉呢?下面将为您…

基于微信小程序和云开发的企业绿色融资平台的设计与实现

文章目录 摘要前言绪论1. 课题背景2. 国内外现状与趋势2.1 国内研究现状2.2 国外研究现状2.3 发展趋势3. 课题内容相关技术与方法介绍1. 微信小程序开发技术2. 腾讯云开发平台3. 绿色项目评估模型4. 智能匹配算法5. 碳核算方法系统分析1. 需求分析1.1 用户需求1.2 功能需求1.3 …

如何自建服务器并开启公网IP:本地内网网址让外网访问详细教学

本地内网环境自建服务器后,如何让外网访问,提供互联网连接服务呢?有不少方法都可以实现,常见的有如公网IP、DDNS动态域名、nat123内网穿透等,下面详细教学。 一、申请开公网IP-----------------公网IP篇-------------…

企业公用电脑登录安全管控的终极方案:ASP操作系统安全登录管控方案

一、引言:公用电脑——企业安全管理的“灰色地带” 在企业办公场景中,公用电脑(如会议室电脑、生产线终端、客服工位)因多用户共用、权限复杂,往往成为安全管理的薄弱环节。员工随意登录、弱密码泛滥、敏感数据泄露事…

HarmonyOS-ArkTS开发指南:从基础到实战

目录 一、基础语法 二、声明式 UI 开发 基本组件结构 三、状态管理 四、生命周期钩子 五、组件化开发 1. 创建自定义组件 2. 组件嵌套 六、事件处理 七、布局系统 八、样式设置 九、条件渲染与列表渲染 十、异步操作 十一、路由导航 开发建议 一、基础语法 ArkT…