1.Unity渲染学习之URP
2.URP(渲染管线定义,源码解析)
3.unity hlsl 9 多光源阴影投射和接收
4.URP管线PBR源码剖析(上)
5.学习笔记Unity 渲染——关于SRP以及SRP的执行过程
6.SRP合批问题
Unity渲染学习之URP
Unity推出SRP系列已有时日,如今许多开发者都倾向于创建自己的渲染管线或对URP进行魔改。深入了解URP的运行处理方式,对我们今后构建自研渲染管线具有很好的借鉴意义。
本文将简要梳理URP的力软7.0.6 源码整个流程,但不会深入探讨某个模块的具体实现,也不会涉及SRP的编写(关于这部分已有专家撰写了详细的教程系列)。若文中存在理解上的错误,敬请专家指正。
所有配图已上传至Github,若在本文中无法清晰查看,可前往该平台寻找对应的高清。
在Unity5多版本期间,我们一直使用的是内置的渲染管线(Built-in)。虽然它提供了一些渲染拓展接口,但面对用户日益增长的多样化需求,这些接口显得力不从心。而且,Unity并未像其他平台那样开源源码。因此,Unity在年推出了SRP(Scriptable Render Pipeline,可编程渲染管线)。SRP对底层渲染进行了更高级别的封装,用户只需通过C#调用相关API,即可自定义渲染管线,筛选需要绘制的物体,指定材质,设置状态,并按照自己的需求进行渲染。这样一来,渲染开发的难度大大降低,因为Unity已经为我们处理了剔除、批处理等任务,我们只需关注自己的逻辑即可。
SRP推出之初,并非所有开发者都具备编写SRP的能力。因此,Unity同步推出了两个基于SRP开发的模板:HDRP(High Definition Render Pipeline,高清渲染管线)和LWRP(Lightweight Render Pipeline,轻量级渲染管线)。HDRP用于服务高性能设备,如PC、主机等;LWRP用于服务性能较低的设备,如移动端等。由于名字的原因,LWRP听起来就像是HDRP的阉割版,让开发者感到不满。手机诱导支付源码随后,Unity将LWRP更名为URP(Universal Render Pipeline,通用渲染管线)。在SRP推出初期,bug频发,API也频繁变动。
目前Unity中留存的管线有原始的Built-in、基于SRP编写的URP和HDRP。本文主要学习URP的流程处理方式。
SRP切换渲染管线是通过Edit -> Project Settings -> Graphics -> Scriptable Render Pipeline Settings来指定对应的渲染管线资产实现的。因此,我们查看URP的入口就是从RenderPipelineAsset开始的。
在编写自己的渲染管线时,我们希望各个功能模块化、可扩展性高、调用关系明确。以下简单介绍URP的组织结构。
还有一个重要的概念是pass,它表示渲染的某个阶段,例如渲染阴影、不透明、半透明、skybox、后处理等。URP提供了一个ScriptableRenderPass基类用于拓展我们的pass,指定我们想要渲染的内容。我们只需将这些pass添加到渲染队列中,URP在具体渲染时会对这些pass进行排序,然后执行绘制。
简单了解了这些概念后,我们可以看看URP的渲染逻辑。URP的整体逻辑如下:
核心的pass实现可以独立出来,想要执行只需将其插入即可。
具体渲染时,Unity会调用渲染管线的Render(...)函数进行一帧的绘制。Render(...)首先初始化全局渲染设置,然后遍历每个相机,对每个相机进行渲染。
接下来简单看看将pass添加到渲染队列的实现:
可以看到这里是按照渲染顺序依次添加了要绘制的pass(其实不按照顺序也可以,因为在执行时会对这些pass进行排序)。在绘制不透明物体时,也分为延迟渲染和前向渲染两个路线。
接下来看看执行这些pass的逻辑:
这里主要是对pass进行排序、分块,设置一些参数,依次执行每个部分,最后绘制一些小玩意。thinkphp 网站源码下载
本文主要简要介绍了URP的处理流程,让大家了解其组织结构。这样在编写SRP或调试URP时,也能作为参考。URP的核心渲染实现是ScriptableRenderPass,这样的设计方便我们日后添加自己的渲染功能,例如使用Render Feature。以下是URP全家福:
URP(渲染管线定义,源码解析)
本文详细解析了Unity渲染管线(URP)的内部工作原理和源码结构,深入探讨了URP如何实现高效的渲染流程和丰富的渲染特性。首先,我们介绍了UnityEngine.CoreModule和UnityEngine.Rendering.Universal命名空间的基本概念,理解了它们在URP中的角色。然后,通过查找CreatePipeline方法和分析UniversalRenderPipeline实例的内部结构,揭示了URP实例化和初始化的过程。
在渲染管线实例阶段,我们聚焦于UniversalRenderPipeline实例的Render方法,以及它在每帧执行的任务,特别是Profiling器的使用,这为性能优化提供了重要的工具。接着,文章深入探讨了ScriptableRenderer类,它实现了渲染策略,包括剔除、照明以及效果支持的描述,展示了其在渲染过程中如何与摄像机交互。
对于渲染过程的细节,文章详细说明了从设置图形参数、执行剔除、初始化光照、执行渲染Pass到后处理阶段的流程。特别关注了渲染Pass的执行,以及如何通过自定义RenderPass来扩展URP的功能。在渲染结束后,文章还介绍了如何使用ProfilingScope进行性能分析,为优化渲染管线提供了实用的工具。
综上所述,本文以深入的技术细节,全面解析了Unity URP渲染管线的内部机制,旨在帮助开发者更好地理解URP的实现原理,进而优化其应用中的渲染性能。
unity hlsl 9 多光源阴影投射和接收
在Unity开发中,实现多光源阴影投射和接收的过程涉及到一些特定的关键字定义和函数调用,本文将详细阐述实现细节以及URP(Unity Render Pipeline)源代码分析,以帮助开发者更好地理解和实现这一功能。
实现多光源阴影投射和接收的最新猴王竞猜源码核心在于定义必要的关键字和调用相关函数。首先需要定义MainLight关键字,这涉及到使用`TransformWorldToShadowCoord()`获取阴影坐标,并通过`MainLightRealtimeShadow(shadowCoord)`获取阴影衰减。对于AdditionalLight,函数调用较为复杂,个人理解可能存在一定混淆。GetAdditionalLight中应使用有shadowMask参数的函数,并以`half4(1,1,1,1)`作为shadowMask参数传递,以正确计算阴影衰减。ShadowCaster Pass负责计算物体的阴影映射并写入纹理,这可以通过调用`UsePass`实现,但需注意支持SRP(Shader Reference Package)的Batcher时,需自行实现ShadowCaster Pass。在设置LightMode以及在计算裁剪空间坐标时,需使用`ApplyShadowBias`函数,并注意z值的正反向判断。
在URP相关源代码分析中,多光源光照和阴影计算主要涉及`Lighting.hlsl`和`Shadows.hlsl`中的函数。GetMainLight函数在无参数的情况下默认阴影衰减为1.0,而有参数时调用`MainLightRealtimeShadow()`或`MainLightShadow()`进行计算。`MainLightShadow`函数直接调用`MainLightRealtimeShadow`并进行混合插值,实现烘焙光照和实时光照的融合。对于AdditionalLight获取,通过调用相关函数并提供index值来获取。在计算阴影时,若定义了相关关键字,则会进行阴影映射采样并返回结果。
在实现过程中,开发者需确保正确使用关键字定义、调用函数以及处理相关参数,以确保多光源阴影投射和接收的准确性和效率。具体实现包括使用URP自带的`ShadowCaster`功能或自定义`ShadowCaster Pass`。最终效果展示则需通过实际项目测试和优化,以确保阴影效果的稳定性和视觉表现。在实践中,可能遇到的问题需仔细排查和解决,以获得满意的结果。
URP管线PBR源码剖析(上)
URP管线与PBR算法的联系并不直接,但新版本的代码结构和算法有了显著变化。本文将深入剖析URP管线下的内置PBR着色器,对比旧版本,探讨主要区别。 此篇内容旨在学习和解答问题,期待大家的反馈和讨论。以下分析分为三步:梳理UniversalFragmentPBR函数的功能和代码结构
解析通用PBR算法
详解ClearCoatPBR算法
首先,UniversalFragmentPBR的主要工作分为数据准备和光照计算。数据准备包括初始化BRDF数据、c 程序案例源码ClearCoat BRDF数据、shadowMask、获取主光源信息和处理SSAO等。光照计算则涵盖了间接光和直接光的计算,如GI、主光、额外像素和顶点光照等。 通用PBR算法的关键部分包括BRDF数据初始化,其中金属和非金属材质的处理有所不同;间接光的计算涉及漫反射和镜面反射;主光光照计算使用了改良的Lambert和Cook-Torrance模型;额外光计算则根据光源类型进行相应调整。 URP版本与旧版的不同点在于支持ClearCoat材质、ShadowMask功能、SSAO效果的整合,以及额外光处理的简化。整体来看,新版本的PBR算法更加灵活且高效。学习笔记Unity 渲染——关于SRP以及SRP的执行过程
本文主要整合了Unity渲染管线的相关资料,重点介绍了Unity的可编辑渲染管线(Scriptable Render Pipeline,SRP)及其执行过程。SRP包含通用渲染管线(Universal Render Pipeline,简称URP)和高清渲染管线(High Definition Render Pipeline,简称HDRP)。用户可以通过C#调用Unity提供的图形API自定义渲染管线,以满足项目需求。若想查看URP代码,可创建URP模板项目或安装URP插件,并在项目文件目录中找到URP的主要源码文件进行查看。
URP代码运行流程涉及到两个关键类:UniversalRenderPipelineAsset类和UniversalRenderPipeline类。UniversalRenderPipelineAsset类用于检查设置是否正确和进行初始化,其中CreatePipeline()和CreateRenderers()函数负责对RendererList进行检查和初始化。UniversalRenderPipeline类是URP渲染的主程序,其Render()方法是相机进行SRP渲染的主方法。在该类中,UniversalRenderPipeline还会调用如RenderCameraStack()、RenderSingleCamera()等方法来实现渲染过程。
渲染过程包括多个步骤:BeginCameraRendering、UpdateVolumeFramework、InitializeCameraData、RenderSingleCamera、EndCameraRendering。其中,RenderSingleCamera()函数尤其关键,它涉及剔除、执行渲染器命令以及提交渲染命令的多个步骤。在执行过程中,Unity会将渲染指令存储在命令列表中,直到最终调用Submit()时做统一的渲染。此外,本文还介绍了SRP Batcher,它通过批处理GPU命令来减少DrawCall之间的设置,从而提高渲染效率。
通过整合这些内容,本文详细阐述了Unity中的SRP及其执行过程,为开发者提供了深入了解渲染管线实现和优化技术的途径。
SRP合批问题
在项目中,使用SRP进行合批时,发现除了Cull和Keywords外,其他因素也可能导致合批失败。例如,使用不同材质的物体之间位置穿插也会造成合批失败。一个场景中如果有三个Shader,三个物体分别使用这三种Shader,无论它们的穿插顺序如何,理论上只需要三个SRP Batch就能完成渲染,但实际上可能会被拆分成4-6个Batch。这需要开发者找出合适的渲染顺序或使用其他方法解决。
场景中常驻的场景相机和UI相机可能导致动态加载的Prefab自带的渲染相机与之前的渲染结果叠加出现问题,尤其是在移动平台上。尽管Overlay相机可以实现正确的叠加,但Base相机却出现花屏现象。这是因为动态加载的Base相机在设置渲染目标时,colorBuffer的Load Action没有正确调整。目前解决方案是将动态相机设置为Overlay,并通过代码将它放入常驻场景相机的CameraStack中。如果在URP下查看Blit操作时发现问题,可以考虑使用类似RenderTexture.DiscardContents的方法来解决。
关于粒子系统是否支持GPU Instancing,答案是肯定的,但在Unity 版本中,粒子系统必须以Mesh模式使用GPU Instancing。粒子系统的实现与GUI的实现类似,数据放在VBO或UBO上效率提升不大,且限制了通用性。对于URP下场景和UI分辨率分离的需求,可以通过将3D场景渲染到RT中,再将RT作为RawImage的Texture渲染到UI中来实现,或者在URP源码中给每个Camera添加修改RenderScale的组件。
urp管线和unity内置管线有哪些区别,好在哪里?
在游戏开发领域,了解不同的渲染管线对提高工作效率和优化游戏性能至关重要。其中,URP(Universal Render Pipeline)和Unity内置管线在实现高质量渲染方面各有特色,本文将深入探讨它们之间的区别及各自的优点。
URP和Unity内置管线在基础策略和渲染处理上存在显著差异,这直接影响到了Shader的编写方式。在URP渲染管线下,使用的是HLSL(High-Level Shader Language)开发Shader,而传统的向前渲染管线则基于Cg语言。这种语言差异为URP提供了更多灵活性和性能优化的机会。
URP渲染管线引入了内置的PBR(Physically Based Rendering)、Unlit、地形等常用Shader,为开发者提供了丰富的资源和现成的解决方案。URP Shader的源代码位于Packages/Universal RP/Shaders目录下,便于参考和学习。相比于标准的Unity Shader,URP Shader内嵌了HLSL代码,简化了复杂性并提高了性能。
在URP渲染管线中,Unlit Shader主要用于绘制3D物体,它采用Unity经典的ShaderLab语法,结构包括SubShader和Pass部分。Unlit Shader有两个SubShader版本,通过ShaderModel版本进行区分,分别对应不同的应用场景。Pass部分包括Unlit Pass、Depth Only Pass和Meta Pass,分别负责绘制、深度测试和静态光照烘焙。
接下来,我们探讨了URP PBR Shader的实现,它支持物理光照、金属度与粗糙度等参数,提供更精确的渲染效果。PBR Shader结构遵循ShaderLab语法,内嵌HLSL Shader编程语言,拥有多种Pass,包括ForwardLit Pass、ShadowCaster Pass等,分别负责3D物体渲染、阴影计算和深度测试等关键步骤。
在光照计算方面,URP PBR Shader通过一系列步骤进行处理,包括初始化双向分布函数BRDF、计算主光源光照、处理全局光照、附加光源光照和自发光等。这种分离式的光照计算方法,使得URP渲染管线在实现高质量渲染效果的同时,优化了性能。
综上所述,URP渲染管线与Unity内置管线在Shader编写、光源处理和光照计算等方面存在明显差异,这些差异为开发者提供了多样化的选择和优化策略。通过深入理解这些差异,开发者能够根据项目需求和性能目标,选择最适合的渲染管线来实现高质量的游戏渲染。
builtIn 转 URP 实操记录
官方介绍概述了 Universal Render Pipeline(URP),虽然内容详尽,但仍需自行研究细节。网络上其他帖子与教程可以结合阅读。
Catlike Coding 的教程较为详尽,尽管版本可能稍旧。
由于初期未仔细阅读文档,踩了许多坑,以下为记录。
builtIn 转换至 URP 的主要处理内容涉及三个方面:shader、后处理和相机。
一、shader
需将旧的 builtIn 替换为 URP 对应的 hlsl 函数,网上有许多相关帖子。
具体内容需根据项目调整,不明函数可查阅源码。
(1)shader 代码修改
编写了一个简单的转换工具,参考 shaderToy 的工具,使用正则表达式替换相应函数。
(2)SRPBatch
SRPBatch 的开启和使用主要涉及多 pass 合批。
例如,三个正方形使用双 pass,同一 shader,不同材质球。按照 SRPBatch,应合成一个。
需解决 CBUFF 和 LightMode 问题。
1、多 pass 情况下,将面板自定义参数写入 CBUFF。
使用 HLSLINCLUDE...ENDHLSL 写入 SubShader 中,无需每个 pass 添加。完成后,Shader 面板将显示可合批。
但在 Frame Debug 面板中发现因多 pass 导致无法合批,涉及第二个问题。
2、LightMode
使用 URP shader 时,光照 pass 会添加额外的 pass。
SRPDefaultUnlit 和 UniversalForward 在同一渲染队列,导致合批失败。
正确做法是自定义 LightMode。
在创建 URP 管线 PipelineAsset_Renderer 添加 Renderer Feature 添加 Render Object。
添加名称、作用 Layer Mask 等。
将多 pass 中的 LightMode 替换为自定义的 customModel。
此时,Frame Debug 将显示合批成功。
(3)C# 部分渲染代码
涉及 commandBuff 以及 OnPreCull、OnPreRender、OnPostRender 和 OnRenderImage 等函数。
这部分尚不熟悉,后续将深入学习。
二、后处理
PostProcessing-v2 是 unity builtIn 的后处理插件,在 URP 下不支持,需使用 URP 的 Volume。
但在使用过程中发现,原本仅对场景进行后处理,结果 UI 界面也被影响,因此需修改相机。
三、相机
URP 下的相机与 builtIn 不同,具体参数和设置可查看官方文档。
Render Type 包括 Base 和 Overlay。
场景中至少需要一个 Base 类型的相机。
为了解决后处理对 UI 的影响,渲染 UI 的 camera 需设置为 Overlay,并在 Base 类型的 camera 中添加进队列。
cameraData 在相机初始化时不一定存在,需添加。
cameraData.cameraStack.Add(uiCamera) 原则上为 Base 类型 camera,uiCamera 为 Overlay。
camera 设置需自行编写管理类。
例如,打开面板时,场景 Base 类型 camera 被禁用,UI Overlay 相机出现问题,需添加不渲染的 Base 类型 camera。
cameraData 和 uiCamera 均为 Base 时,在 loading 场景时设置会警告并卡死。
需在添加前判断 camera 类型。
在非 loading 情况下,uiCamera 已修改为 Overlay,但判断仍为 Base,但添加后正常。
添加判断导致原本可堆叠的 camera 失效。
需进一步验证。
目前仅记录以上内容,可能存在不足,后续将深入学习弥补。
unity urp源码学习一(渲染流程)
sprt的一些基础:
绘制出物体的关键代码涉及设置shader标签(例如"LightMode" = "CustomLit"),以确保管线能够获取正确的shader并绘制物体。排序设置(sortingSettings)管理渲染顺序,如不透明物体从前至后排序,透明物体从后至前,以减少过绘制。逐物体数据的启用、动态合批和gpuinstance支持,以及主光源索引等配置均在此进行调整。
过滤规则(filteringSettings)允许选择性绘制cullingResults中的几何体,依据RenderQueue和LayerMask等条件进行过滤。
提交渲染命令是关键步骤,无论使用context还是commandbuffer,调用完毕后必须执行提交操作。例如,context.DrawRenderers()用于绘制场景中的网格体,本质上是执行commandbuffer以渲染网格体。
sprt管线的基本流程涉及context的命令贯穿整个渲染流程。例如,首次调用渲染不透明物体,随后可能调用渲染半透明物体、天空盒、特定层渲染等。流程大致如下:
多相机情况也通过单个context实现渲染。
urp渲染流程概览:
渲染流程始于遍历相机,如果是游戏相机,则调用RenderCameraStack函数。此函数区分base相机和Overlay相机:base相机遍历渲染自身及其挂载的Overlay相机,并将Overlay内容覆盖到base相机上;Overlay相机仅返回,不进行渲染操作。
RenderCameraStack函数接受CameraData参数,其中包含各种pass信息。添加pass到m_ActiveRenderPassQueue队列是关键步骤,各种pass类实例由此添加至队列。
以DrawObjectsPass为例,其渲染流程在UniversialRenderer.cs中实现。首先在Setup函数中将pass添加到队列,执行时,执行队列内的pass,并按顺序提交渲染操作。