深入URP之Shader篇2: 目录结构和Unlit Shader分析[上]

news2024/9/29 1:17:42

Unity和URP版本

我使用的Unity版本为2020.3.33f1,对应的URP和SRP Core版本为10.8.1。阅读URP源码建议把package从Library/PackageCache中拷贝到Packages目录,也就是自定义package的方式,然后推荐使用VS code打开工程,这样可以很方便的跳转代码阅读。

URP Shader目录结构

首先,我们看一下URP源码的目录结构,看一下Shader代码的位置:
在这里插入图片描述

Shader代码位于Shader目录以及ShaderLibrary目录中,先总体看一下都有哪些内容。

在这里插入图片描述
在这里插入图片描述

从hlsl文件的名称中我们就可以发现很多URP的渲染管线功能了,比如渲染阴影贴图使用的ShadowCasterPass.hlsl,Z-PrePass使用的DepthOnlyPass.hlsl,以及众多我们在材质Inspector中可以选择的URP Shader:

在这里插入图片描述

从本篇开始,我们会逐一去学习分析这些Shader。

SRP Core包

另外,URP的Shader还会引用SRP Core这个包中的ShaderLibrary:

在这里插入图片描述

这个SRP Core提供了URP/HDRP共享的一些功能的实现,如果需要自定义一个SRP,使用这个库也可以大大简化工作。其ShaderLibrary中包含了很多基础和核心Shader函数以及宏定义。

Unlit Shader

本篇分析第一个shader: Unlit Shader,即URP Shader目录中的Unlit.shader。这个Shader虽然是最简单的无光照Shader,但是其结构以及用法体现了URP Shader甚至URP渲染管线的体系架构。由于这是我们分析的第一个Shader,会有很多公共的基础内容,因此篇幅较长,因此分为上下两篇。本篇中我们分析unlit shader的属性部分,重点是ShaderGUI对属性的处理。

Properties

先看看属性部分,Unlit Shader的属性不多,除了贴图、颜色、Alpha Cutout之外,就是混合模式相关参数,以及渲染队列偏移值。

Properties
    {
        [MainTexture] _BaseMap("Texture", 2D) = "white" {}
        [MainColor]   _BaseColor("Color", Color) = (1, 1, 1, 1)
        _Cutoff("AlphaCutout", Range(0.0, 1.0)) = 0.5

        // BlendMode
        [HideInInspector] _Surface("__surface", Float) = 0.0
        [HideInInspector] _Blend("__blend", Float) = 0.0
        [HideInInspector] _AlphaClip("__clip", Float) = 0.0
        [HideInInspector] _SrcBlend("Src", Float) = 1.0
        [HideInInspector] _DstBlend("Dst", Float) = 0.0
        [HideInInspector] _ZWrite("ZWrite", Float) = 1.0
        [HideInInspector] _Cull("__cull", Float) = 2.0

        // Editmode props
        [HideInInspector] _QueueOffset("Queue offset", Float) = 0.0

        // ObsoletePropertes
        [HideInInspector] _MainTex("BaseMap", 2D) = "white" {}
        [HideInInspector] _Color("Base Color", Color) = (0.5, 0.5, 0.5, 1)
        [HideInInspector] _SampleGI("SampleGI", float) = 0.0 // needed from bakedlit
    }

  • URP统一使用 _BaseMap 作为主贴图,_BaseColor作为主颜色。相应的,老的名称被归于ObsoletePropertes部分,在这儿还保留着是为了兼容老的材质用法。
  • [HideInInspector]表示不在Inspector中展示,这往往因为该属性是内部处理的,或者是使用了自定义的ShaderGUI展示。在这儿两种原因都有。
  • unlit shader使用的ShaderGUI代码为shader最下方定义的:CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.UnlitShader",但其实主要的工作是在基类 BaseShaderGUI中完成。需要注意的是,这个BaseShaderGUI是处理很多不同Shader的公共属性的,因此其中有些属性unlit shader并没有。

unlit shader的相关属性的处理

下面研究unlit shader中的属性在BaseShaderGUI中如何处理。

_AlphaClip和 _Cutoff

_AlphaClip是个开关,表示是否启用Alpha clipping,在_AlphaClip开启时,才可以编辑_Cutoff值,显示在Inspector上就是这样:

在这里插入图片描述

SetupMaterialBlendMode函数中,可以看到_AlphaClip的开关决定了是否启用_ALPHATEST_ON关键字,这个关键字是一个Shader Feature关键字,在shader代码中会根据是否启用这个关键字决定是否执行alpha clip操作:

            bool alphaClip = false;
            if(material.HasProperty("_AlphaClip"))
                alphaClip = material.GetFloat("_AlphaClip") >= 0.5;

            if (alphaClip)
            {
                material.EnableKeyword("_ALPHATEST_ON");
            }
            else
            {
                material.DisableKeyword("_ALPHATEST_ON");
            }

_Surface, _QueueOffset 以及 Blend

_Surface属性决定材质是透明材质还是不透明材质,如果是透明材质,就会启用Blend相关属性的编辑:

DoPopup(Styles.surfaceType, surfaceTypeProp, Enum.GetNames(typeof(SurfaceType)));
if ((SurfaceType)material.GetFloat("_Surface") == SurfaceType.Transparent)
    DoPopup(Styles.blendingMode, blendModeProp, Enum.GetNames(typeof(BlendMode)));

在这里插入图片描述

  • 透明材质和不透明材质会设置不同的RenderQueue,对于不透明材质设置如下:
                if (surfaceType == SurfaceType.Opaque)
                {
                    if (alphaClip)
                    {
                        material.renderQueue = (int) RenderQueue.AlphaTest;
                        material.SetOverrideTag("RenderType", "TransparentCutout");
                    }
                    else
                    {
                        material.renderQueue = (int) RenderQueue.Geometry;
                        material.SetOverrideTag("RenderType", "Opaque");
                    }

                    material.renderQueue += material.HasProperty("_QueueOffset") ? (int) material.GetFloat("_QueueOffset") : 0;
                    material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.One);
                    material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.Zero);
                    material.SetInt("_ZWrite", 1);
                    material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                    material.SetShaderPassEnabled("ShadowCaster", true);
                }

不透明根据是否启用AlphaClip,设置renderQueue为AlphaTestGeometry,并且会设置相应的RenderTypeTag值。_QueueOffset用于在当前队列位置上进行偏移,这样可以单独指定这个材质的渲染顺序,利用这点我们可以让同一材质的物体排列在一起渲染有利于SRP Batcher合批。这个用法效果和直接在sub shader的QueueTags中使用+/-来偏移值是一样的,但是提供了UI的编辑。
另外不透明材质会默认设置_SrcBlend为One,_DstBlend为Zero,以及默认开启_ZWrite。同时会禁用关键字_ALPHAPREMULTIPLY_ON,以及启用ShadowCaster这个pass来渲染阴影贴图。

  • 注意以上这些操作都是编辑器操作,相应的材质会被修改设置,然后序列化保存,游戏运行时反序列化材质获取这些设置。
  • 下面看一下透明材质的处理:
                    BlendMode blendMode = (BlendMode) material.GetFloat("_Blend");

                    // Specific Transparent Mode Settings
                    switch (blendMode)
                    {
                        case BlendMode.Alpha:
                            material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha);
                            material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                            break;
                        case BlendMode.Premultiply:
                            material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.One);
                            material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                            material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                            break;
                        case BlendMode.Additive:
                            material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha);
                            material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.One);
                            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                            break;
                        case BlendMode.Multiply:
                            material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.DstColor);
                            material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.Zero);
                            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                            material.EnableKeyword("_ALPHAMODULATE_ON");
                            break;
                    }

                    // General Transparent Material Settings
                    material.SetOverrideTag("RenderType", "Transparent");
                    material.SetInt("_ZWrite", 0);
                    material.renderQueue = (int)RenderQueue.Transparent;
                    material.renderQueue += material.HasProperty("_QueueOffset") ? (int) material.GetFloat("_QueueOffset") : 0;
                    material.SetShaderPassEnabled("ShadowCaster", false);

同样是根据不同的BlendMode设置材质的属性值,并开启或禁用相关关键字,设置材质的Tag,以及设置renderQueue,并且关闭ShadowCasterpass。

本篇小结

  • UPR的内置shader会使用ShaderGUI对材质进行设置,ShaderGUI会设置材质的属性以及关键字等信息。
  • unlit shader材质的渲染队列是由Surface是否透明和是否开启AlphaClip共同决定的,并且使用一个queue offset可以微调材质在队列中的位置。
  • unlit shader包含了透明和不透明,以及alpha clip材质,这几种可能性通过一个shader包含了,而差别仅仅是不同的属性值和少量的关键字。这即减少了不同shader的数量,也有利于SRP Bathcer合批。

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

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

相关文章

Golang【Web 入门】 08 集成 Gorilla Mux

阅读目录集成 Gorilla Mux为什么不选择 HttpRouter?安装 gorilla/mux使用 gorilla/mux迁移到 Gorilla Mux1. 新增 homeHandler2. 指定 Methods () 来区分请求方法3. 请求路径参数和正则匹配4. 命名路由与链接生成集成 Gorilla Mux 我们将选用 gorilla/mux 来作为 g…

CSS页面布局(超详解)

目录 1 CSS页面布局概述 1.1 概述 1.2 网页栏目划分 1.3 元素类型转化 1.3.1 块元素 1.3.2 行内元素 1.3.2 块元素和行内元素的转换 1.4 定位 1.4.1 静态定位 1.4.2 相对定位 1.4.3 绝对定位 1.4.4 固定定位 1.4.5 定位元索的层叠次序 1.5 浮动 1.5.1 概述 1.5…

JAVA中如何精确取到时间

文章目录0 写在前面1 使用方法2 举例3 写在最后0 写在前面 做业务的时候,总要统计数据,几月份到几月份的全部数据。这个时候就要找到起始月份的具体时间和终止月份的具体时间。 此时我们用原始的Date类去处理就比较麻烦,可以自己写一个工具类…

Web3中文|什么是以太坊虚拟机(EVM),它是如何工作的?

来源 | cointelegraph 编译 | DaliiNFTnews.com 以太坊已成为仅次于比特币的第二重要区块链。以太坊能发展得这么好,它的原生Solidity编程语言和以太坊虚拟机(EVM)发挥了重要的作用。 以太坊区块链凭借自身拥有的灵活性、大量可用的开发工…

MySQL高级SQL语句

一.准备 mysql -uroot -p123123create database train_ticket; #创建库use train_ticket; create table REGION(region varchar(10),site varchar(20)); create table FARE(site varchar(20),money int(10),date varchar(15)); #创建表desc REGION; desc FARE; #查看表结构ins…

[附源码]计算机毕业设计云南美食管理系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

浅析linux内核网络协议栈--linux bridge(二)

6. 网桥数据转发 6.1 网桥数据包入口 网桥是一种2层网络互连设备,而不是一种网络协议。它在协议结构上并没有占有一席之地,因此不能通过向协议栈注册协议的方式来申请网桥数据包的处理。相 反,网桥接口(如上述的eth1&#xff09…

mysql—MHA原理与实现

官方介绍:https://code.google.com/p/mysql-master-ha/ MySQL复制集群中的master故障时,MHA按如下步骤进行故障转移: 从上图可总结MHA工作步骤为: -从宕机崩溃的master保存二进制日志事件(binlogevents)。 -识别含有最新更新的s…

macOS Electron 环境安装时的错误 Cannot find module ‘macos-alias‘ 解决

macOS Electron 环境安装时的错误 Cannot find module ‘macos-alias’ 解决 一、问题描述 在想 make 并发布软件版本的时候,现出这个错误: ❯ Making distributables✖ Making a dmg distributable for darwin/arm64› Cannot find module macos-ali…

SSM处理过程

SSM框架是spring MVC ,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层 使用spring MVC负责请求的转发和视图管理 spring实现业务对象管理&#xf…

DSP篇--C6678功能调试系列之TIMER、UART调试

目录 1、TIMER计时器调试 2、UART串口调试 2.1 核传输 2.2 EDMA传输 1、TIMER计时器调试 The TMS320C6678 device has sixteen 64-bit timers in total. Timer0 through Timer7 are dedicated to each of the eight CorePacs as a watchdog timer and can also be used as g…

黄东旭:开发者的“技术无感化”时代,从 Serverless HTAP 数据库开始 | PingCAP DevCon 2022

12 月 1 日,以"去发现,去挑战"为主题的 PingCAP DevCon 2022 主论坛在线上成功举办,为数万观众带来一场技术盛宴。PingCAP 联合创始人兼 CTO 黄东旭,在大会上分享了“The Future of Database”的主题演讲,分…

Unity记录几个5.x升级到2018问题

XLua的 ILType Emit等C#框架问题 本来是Unity5.x,貌似是最旧的代码 。Net 2.0 无奈升级用了Unity2018之后,只支持4.x, 在PlayerSetting面板,改成.Net3.5,居然阔以了 (Unity2018.7 - 支持的最低,.Net 3.x…

使用 Learner Lab - 学生

使用 Learner Lab - 学生 AWS Academy Learner Lab 是提供一个帐号让学生可以自行使用 AWS 的服务,让学生可以在 100 USD的金额下,自行练习所要使用的 AWS 服务,AWS Academy 学习平台建立 Learner Lab - 教师 这篇文章介绍老师如…

【JVM】 类加载器 ClassLoader

一、JVM 类加载器 JVM 具有 4 种类加载器: 引导类加载器 : 负责加载支持 JVM 运行的位于 JRE 的 lib 目录下的核心类库,比如 rt.jar 、charsets.jar 等等扩展类加载器:负责加载支撑 JVM 运行的位于 JRE 的 lib 目录下的 ext 扩展…

java计算机毕业设计ssm宁夏源沣医药线上销售平台thd3v(附源码、数据库)

java计算机毕业设计ssm宁夏源沣医药线上销售平台thd3v(附源码、数据库) 项目运行 环境配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&a…

戳进来,带你走近飞凌嵌入式旗舰级AIoT芯RK3588开发板

飞凌嵌入式OK3588-C开发板现已正式发售!真8K、强大算力、出色的多媒体性能、丰富的用户资料......多重优势为您带来更优质的体验! OK3588-C开发板基于Rockchip旗舰级AIoT处理器RK3588设计开发,先进的8nm制程工艺、Big.Little大小核架构以及L3…

[附源码]计算机毕业设计springboot学分制环境下本科生学业预警帮扶系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

基于PHP+MySQL班级信息发布和管理系统的设计与实现

一直以来我国领导人提倡以人为本的治国方案,而大学是未来人才的培养基地,如何能够更好的对学生信息进行管理,是很多高校一直在研究的一个问题,只有更加科学的对学生信息进行管理,才能够更加积极的培养国家的栋梁之才。…