Shader 基础之 Unity Shader概念

news2024/9/21 21:00:38

目录

目录

Shader compilation

Conditionals in shaders

Different types of conditionals

Switch code branch at runtime

Branching in shaders

Static branching

How to use static branching

Dynamic branching

How to use dynamic branching

Shader variants

Deduplication of shader variants

Check how many shader variants you have

获取editor下使用的变体数量

获取build时的变体数量

Shader keywords

Definition type: “multi compile” or “shader feature”

Local or global scope

Stage-specific keywords

Create a shader variant for disabled keywords

Using shader keywords with C# scripts

Local Shader Keywords:

Global Shader Keywords: 

How Unity loads and uses shaders

Prewarming shader variants

Profiler 中对shader loading 的标记:

Shader compilation

1. 编译分为两种:Editor、Runtime

Editor:

  • 预编译,编译好的会缓存到Library/ShaderCache 下,下次用到该变体的时候,直接重缓存里取,删除Library文件夹,会重新编译。
  • 编译在Editor 下是异步的,即在后台编译,在完成之前,物体呈cyan色;
  • Unity 编辑器右下角可以看到编译的进度,在preference ->Editor 下可以开启/关闭是否异步编译,一般CPU的一个核对应一个编译job

Runtime:

  • 在build的时候,如果使用shader_feature 来定义变体,会剔除没有用到的变体,然后编译所有用到的变体,放到包体里面

2. 不同的平台,Shader编译器会有所不同

3. 一个shader包含在多个material里面,打进assetbundle中,会导致有多份shader,同时也打断了合批,可以使用 Asset Bundle Browser 来检查bundle的依赖

Conditionals in shaders

  • 有时候,想要相同的着色器在不同的情况下做不同的事情。
  • 例如,为不同的materail配置不同的设置,为不同的硬件定义功能,或者在运行时dynamic改变着色器的行为。可能还希望避免在不需要时执行计算开销较大的代码,例如纹理读取、顶点输入、插值器或循环。
  • 使用条件来定义GPU只在特定条件下执行的行为。

Different types of conditionals

shader 使用条件的方法有下面三种:

  • Static branching: the shader compiler evaluates conditional code at compile time.Use preprocesser constants and macros.
  • Dynamic branching: the GPU evaluates conditional code at runtime.
  • Shader variants
    : Unity uses static branching to compile the shader source code into multiple shader programs. Unity then uses the shader program that matches the conditions at runtime.

使用 shader variants 这种方法,build的时候会剔除未使用的变体,所以这种情况,应该避免在c#中enable/disable  shader_feature keywords,因为有可能启用的变体,没有打到包里,如果该变体没有,则会选择一个默认的使用

如果需要在c#中enable/disable shader_feature keywords,则应该让所有的shader变体都包含在包体里面,采用下面两种方法:

  • 创建一个 shader variant collection 资源,包所有的变体,添加进去
  • Include a Material in your build for every combination of shader_feature keywords you want to use.

Switch code branch at runtime

在c#代码中切换shader的分支,有两种方法:

  • 在shader中声明multi_compile 关键字,缺点是编译的变体非常多,占内存
  • 使用dynamic branch,缺点是耗费GPU
#pragma shader_feature REFLECTION_TYPE1 REFLECTION_TYPE2 REFLECTION_TYPE3
Shader directiveBranching typeShader variants Unity creates
shader_featureStatic branching

Variants for keyword combinations you enable at build time

(只是enable的shader_feature的组合)

multi_compileStatic branchingVariants for every possible combination of keywords
dynamic_branchDynamic branchingNo variants

Branching in shaders

根据shader 执行branch 的方式,分为两种:

  • Static branching
  • Dynamic branching

Static branching

在运行之前就已经编译好的叫静态branch

  • 优点:由于构建的时候,会剔除掉未使用的branch,所以构建的包体小,时间短,对性能没影响
  • 缺点:因为剔除的原因,一些branch 不能在runtime 中使用

How to use static branching

三种方法:

  • 手写的 shaders:
    • Use #if, #elif, #else, and #endif preprocessor directives, or #ifdef and #ifndef preprocessor directives to create static branches.
    • Use an if statement that evaluates a compile-time constant value. Although if statements can also be used for dynamic branches, the compiler detects the compile-time constant value and creates a static branch instead.
    • Unity provides built-in macros for some compile-time constants that you can use with static branches.

Note: Static branching is available only in hand-coded shaders. You cannot create static branches in Shader Graph.

Dynamic branching

它又分为两种:

  • 基于uniform variables
  • 基于任何其他other runtime value

基于uniform variables通常更有效,因为uniform variables对于整个drawcall是恒定的

  • 优点:可以实时的根据动态的值,来采取不同的策略
  • 缺点:耗费GPU,因为GPU执行过程是一个单元一个单元并行的,non-uniform variables会打断这个并行,因为有的单元去处理另一个分支,有的去处理相反的分支,如果一个处理完,另一个就会等待另一个,uniform variables的值,是所有的单元都去处理其中一个分支,性能会相对好

Note:所有的分支都会编译成程序,写进shader里面,这会增加文件的大小,但是相比较多个变体来说,它还是小的

How to use dynamic branching

You can use dynamic branching in your shaders in the following ways:

  • In hand-coded shaders, use an if statement that evaluates runtime state. You can use attributes to force the GPU to execute both branches, or to execute only one branch.
  • In Shader Graph, use a Branch Node. This always executes both branches.

Shader variants

使用 shader keywords.来配置variants,构建的时候,每一个变体,都是一段shader 代码

  • 优点:比dynamic branch 耗费更低的GPU性能
  • 缺点:多了,会增加内存,和加载时间

Deduplication of shader variants

  • After compilation, Unity 自动识别相同通道内的相同变体,并确保这些相同的变体指向相同的字节码. This is called deduplication.
  • Deduplication 防止同一pass中的相同变体增加文件大小,但是也会增加编译的时间,需要踢除不必要的变体 strip unneeded variants.

Check how many shader variants you have

获取editor下使用的变体数量

Select Save to asset… to create a shader variant collection asset.

获取build时的变体数量

打开Editor.log 文件(menu: Window > General > Console and select Open Editor Log from the Console window menu.),搜索 Compiling shader

Shader keywords

通过shader keywords 的方法,可以在shader 里面使用条件语句

一个集合的keywords 叫作Keyword,里面的单个keyword叫作state

Definition type: “multi compile” or “shader feature”

shader 中声明keywords的type有两种:

1.multi compile:这里面声明的任何keyword 都会编译成变体

2.shader feature:只有enable的keyword才会编译成变体打进包里,其它的都被裁剪了

Note: 如果把shader添加projectsetting->graphics-> Always Included Shaders 里面,unity 会把它里面的所有keyword都包含在包体里面,即使type 是 shader_feature.

Local or global scope

默认声明的keyword 都是global的,但是可以在声明keyword type的时候,加上后缀_local 来表示是local的,加上之后表示不可override的,也就是同名的不能复写它

Stage-specific keywords

默认,Unity为每个stage声明相同的变体,比如, shader中包含 vertex stage and a fragment stage, Unity 会为它们声明同样的变体,假如只在一个stage中用到了keywords,就会导致变体在另一个stage中是重复的,Unity 会自动识别,并裁剪它们,所以不会增加包体大小, but they still result in wasted compilation time, increased shader loading times, and increased runtime memory usage.

为了避免这个问题,在声明keywords type的时候,加上特定的后缀,表示是哪个stage用的

比如:

  • _vertex
  • _fragment
  • _hull
  • _domain
  • _geometry
  • _raytracing

#pragma shader_feature_fragment RED GREEN BLUE--表明是在fragment stage用的

Create a shader variant for disabled keywords

如果用 shader_feature 创建 single keyword, 当该keyword disable 的时候Unity 会自动创建second variant. This helps reduce the number of keywords you need to enable and disable. For example, the following code creates 2 variants:

#pragma shader_feature EXAMPLE_ON

如果使用 multi_compile/ shader_feature 创建 two or more keywords, 使用 _ ,当该集合中的所有关键字被禁用时,创建一个着色器变体

#pragma multi_compile _ EXAMPLE_ON
#pragma shader_feature _ RED GREEN BLUE WHITE

Using shader keywords with C# scripts

  • c#中shader keyword的概念分为两种:Local Shader Keywords、Global Shader Keywords,这是在c#中的概念,在shader中,local 和global 的区别在于,local 需要在type后面加后缀_local 来声明其是local的,否则是global的。
  • c# 中shader 的keywords存储在  LocalKeywordSpace 结构体内,通过Shader.keywordSpace,compute shader中通过ComputeShader-keywordSpace.来访问
  • local 和 global通过属性  isOverridable 表明,为true 说明是global,false 是local,global不用主动声明,不是local 就是global

Local Shader Keywords:

  • 不可以被override,即同名的不会影响它的值
  • 只影响单个的shader、compute shader
  • 通过 Material.IsKeywordEnabled or Material.EnableKeyword. For a compute shader, use ComputeShader.IsKeywordEnabled  检验开启/关闭
  • 通过 Material.SetKeyword, Material.EnableKeyword, or Material.DisableKeyword. For a compute shader, use ComputeShader.SetKeyword, ComputeShader.EnableKeyword, or ComputeShader.DisableKeyword. 开启/关闭

Global Shader Keywords: 

  • 可以被override
  • 影响过个shader、compute shader
  • 通过 Shader.IsKeywordEnabled or Shader.EnableKeyword or ComputeShader.enabledKeywords检验开启/关闭
  • 通过 Shader.SetKeyword, ComputeShader.EnableKeyword, or ComputeShader.DisableKeyword开启 /关闭

在运行时,切换不同的变体,容易对性能造成影响,如果该变体之前没有加载过,且是复杂的变体,容易造成画面卡顿的情况。如果使用global keywords,同时修改多个shader,也容易造成同样的问题

How Unity loads and uses shaders

  • Unity 在应用内加载编译好的变体
  • 加载场景或者assetbundle(resource 内的资源)的时候,会加载该场景或资源用到的所有变体到CPU内,然后再解压到CPU的另一块内存的地方,所占内存的大小 可以在 Player settings->Other Settings > Shader Variant Loading  内更改
  • 当第一次用到一个变体的时候,CPU会把资源数据发送给GPU,而不是一次性把所有变体都放到GPU,GPU会对相应的变体,生成一个GPU-specific version of the shader variant,缓存下来,下次再用就不会重新发送了
  • 如果该变体在场景内没有任何引用,Unity 会从CPU、GPU移除掉它

Prewarming shader variants

为了避免使用时,加载出停滞的情况,可以采用预加载的方式:

  • Prewarm a Shader object or shader variant collection using the Experimental.Rendering.ShaderWarmup API.
  • Prewarm a shader variant collection by using the ShaderVariantCollection.WarmUp API.
  • Prewarm all variants of all Shader objects currently in memory using the Shader.WarmupAllShaders API.

也可以在projectsetting->graphics  里面配置Preloaded shaders section of the Graphics Settings window. Unity uses the ShaderVariantCollection.WarmUp API to load and prewarm the shader variant collections when your built application starts.

Profiler 中对shader loading 的标记:

  • Shader.ParseThreaded、 Shader.ParseMainThread for Unity loading the shader object from serialized data.
  • Shader.CreateGPUProgram for Unity creating a GPU-specific version of a shader variant

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

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

相关文章

选读SQL经典实例笔记04_日期运算(上)

1. 年月日加减法 1.1. DB2 1.1.1. sql select hiredate -5 day as hd_minus_5D,hiredate 5 day as hd_plus_5D,hiredate -5 month as hd_minus_5M,hiredate 5 month as hd_plus_5M,hiredate -5 year as hd_minus_5Y,hiredate 5 year as hd_plus_5Yfrom empwhere dept…

【计算机网络】第三章 数据链路层(虚拟机与局域网)

文章目录 3.9 以太网交换机自学习和转发桢的流程3.10 以太网交换机的生成树协议STP3.11 虚拟局域网3.11.1 虚拟局域网VLAN概述3.11.2 虚拟局域网VLAN的实现机制 3.9 以太网交换机自学习和转发桢的流程 以太网交换机的自学习和转发数据帧的流程如下: 自学习&#x…

Mac中使用命令行来加密压缩zip文档

背景 最近需要对一些文件加密,但是Mac上没有找到相应的加密工具,macOS中创建密码保护的压缩 zip 文件很容易并且不需要任何额外附加物或下载。使用命令行的方式处理即可。对压缩包加密之后便意味着有人想要解压缩zip文件时,必须输入正确的密码…

Layui入门必看:登录注册界面搭建与功能开发解析

目录 Layui介绍 什么是Layui? Layui入门 Layui登录实例 导入jar 配置 导入Layui 编写公共jsp 编写代码 Layui注册实例 代码实例 Layui介绍 Layui是一款面向前端开发者的轻量级JavaScript库,旨在简化网页开发过程。它提供了丰富的基础UI组件和…

电气设备漏电保护方式研究

摘要:电气设备漏电故障可能对无防范意识人员产生触电危害,轻者灼伤人体接触位置,重者危及人员生命,甚至会产生漏电火花引起火灾,给企业带来不可估计的损失。文中浅谈电气设备漏电危害性及漏电保护方式,意指…

C++使用rapidjson读写json数据

一、背景 RapidJSON简介及使用_fengbingchun的博客-CSDN博客 rapidjson是腾讯的高效C Json解析器,只有头文件,可跨平台使用 mirrors / Tencent / rapidjson GitCode 二、读数据 使用rapidjson解析和组装json_youyicc的博客-CSDN博客 三、写数据 …

AES加解密算法强化训练

目标: 使用openssl算一遍,再使用网页在线工具算一遍,看看结果是否一样 构造数据 如何编写一个二进制规律性的文件, 比如你可以编写一个"0123456789abcdef"的文本文件,记得删除换行符 然后用ultraedit打开,…

常见加密算法介绍

文章目录 一、背景:二、几种常见的加密算法1. 不可逆加密算法(哈希算法):1.1 MD51.1.1 优点:1.1.2 缺点:1.1.3 Demo:1.1.4 案例分析: 1.2 SHA-2561.2.1 Demo:1.2.2 案例分…

day19三数之和 int *returnSize,int ** returnColumnSizes的理解

题目描述 *1.关于参数 int returnSize, int ** returnColumnSizes的理解 具体看这篇文章 [https://blog.csdn.net/m0_52775920/article/details/121461911?spm1001.2014.3001.5502] (1)*returnSize 的理解 returnSize 返回大小为returnSize的二维数组&…

代码随想录算法二刷 day49 | 动态规划 之121 买卖股票的最佳时机 122 买卖股票的最佳时机II

day49 121. 买卖股票的最佳时机1.确定dp数组(dp table)以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组 122.买卖股票的最佳时机II 121. 买卖股票的最佳时机 题目链接 解题思路: 动规五部曲分析如下&#xf…

【Linux-Windows】 关于PCI和PCIE接口

【Linux-Windows】 关于PCI和PCIE接口 1、背景2、物理外观区别3、其它区别 1、背景 最近在配置电脑主机。 由于要在主机上安装了一块PCI接口的固高控制卡,其系统架构如下图: 使用的PCI接口的固高控制卡外形如下图: 为此,我额外…

2023-7-10-第十五式命令模式

🍿*★,*:.☆( ̄▽ ̄)/$:*.★* 🍿 💥💥💥欢迎来到🤞汤姆🤞的csdn博文💥💥💥 💟💟喜欢的朋友可以关注一下&#xf…

java 代码块

文章目录 代码块的描述静态代码块静态代码块的特点 非静态代码块分析加载顺序 代码块的描述 代码块(或初始化块)的作用: 对Java类或对象进行初始化 代码块(或初始化块)的分类: 一个类中代码块若有修饰符,则只能被static修饰,称为…

嵌入式_一种非常简单实用的基于GD32的裸机程序框架

嵌入式_一种非常简单实用的基于GD32的裸机程序框架 搜索了一下关于GD或ST裸机程序的问题,网上有非常多也非常的例子,但是针对裸机开发的程序框架却比较少,这里简单整理了一下在项目中使用过的一种比较小巧便携的裸机程序框架(确切…

cloud Alibab+nacos+gateway集成swaggerui,统一文档管理(注意点)

首先说明&#xff1a;本文只说整合注意点 效果图和功能参考链接 1.使用gateway访问nacos服务&#xff0c;503 在网关服务添加依赖即可解决 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign&…

1.入门matlab数理统计随机数的产生(matlab程序)

1.简述 一、常见分布的随机数的产生 随机数是专门的随机试验的结果。在统计学的不同技术中需要使用随机数&#xff0c;比如在从统计总体中抽取有代表性的样本的时候。而matlab直接提供了产生随机数的通用函数&#xff0c;但针对不同的分布&#xff0c;函数形式会有所不同&#…

DITA技巧:将DITA或Markdown发布成CHM

- 1 - 场景 CHM是英文Compiled HTML Help的缩写&#xff0c;是微软公司专有的联机帮助格式&#xff0c;由HTML页面、索引和其他导航工具的集合组成。这些文件被压缩并部署为二进制格式&#xff0c;扩展名为.CHM&#xff0c;用于编译HTML。CHM格式通常用于软件文档。 虽然CHM…

16. 最接近的三数之和(双指针+减去多余步骤)

16. 最接近的三数之和 双指针减去多余步骤测试代码测试结果 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 示例 1&#xff1a; 输入&…

JSP环境搭建教程(保姆级!!)

简介 Java Server Pages (JSP) 是一种由 Sun Microsystems 开发的用于创建动态网页的技术。它是 Java EE (Java Enterprise Edition) 技术的一部分&#xff0c;允许开发者在 HTML 中嵌入 Java 代码&#xff0c;从而实现动态内容的生成。 JSP 主要由两部分组成&#xff1a;静态…

LiveGBS流媒体平台GB/T28181功能-如何对接海康大华宇视等监控摄像头报警消息报警订阅国标报警信息

LiveGBS流媒体平台GB/T28181功能-如何对接海康大华宇视等监控摄像头报警消息报警订阅国标报警信息 1、报警信息1.1、报警查询1.2、配置开启报警订阅1.2.1、国标设备编辑1.2.2、选择开启报警订阅 1.3、配置摄像头报警1.3.1、配置摄像头报警通道ID1.3.2、配置摄像头开启侦测1.3.3…