1.技术美术(TA)技术部分文章汇总(持续更新)
2.Unity的URP HDRP等SRP管线详解(包含源码分析)
3.unity urp源码学习一(渲染流程)
4.urp管线和unity内置管线有哪些区别,好在哪里?
5.unity hlsl 9 多光源阴影投射和接收
6.SRP合批问题
技术美术(TA)技术部分文章汇总(持续更新)
本文汇集了作者个人学习路径中的关键技术资源,旨在分享给需要的朋友们,希望有所帮助。 学习顺序大致按照作者的实践路径展开:首先从Unity的内置管线开始,包括SRP和URP自定义管线,作为技术基础,gompg底层源码为后续图形算法的实现打下基础。这是第一阶段,主要涉及实践和理论理解。
接下来是深入研究Unity引擎,从官方教程入手,特别是材质部分,然后逐步理解源码并进行修改,这是第二阶段,侧重于实践和代码理解。
学习过程中,切忌急于求成,如UnityShader相关资源,如Unity Standard Shader技术分析和内置着色器源码剖析,都是逐步突破的阶段。
算法实现方面,通过庄懂老师的课程,理解技术美术如何服务于艺术表达,如兰伯特模型的灵活运用。 对于Shader,从SRP到URP的转换路径有指导意义,比如官方资源和社区分享的文章。继续深入,光追技术的学习从基础的raytracing系列文章开始,然后是Unity的光追实现,以及全局光照和路径追踪等技术。
PBR(物理基础渲染)是另一个重要领域,包括光照模型、阴影处理等,推荐的书籍和实践指南不容忽视。
在实时渲染和图形基础渲染管线的学习中,Unity的官方资源和Games系列教程是关键,以及GAMES课程的实践作业。 理解计算机图形学的数学基础,如几何、光影、时空模式源码纹理处理等,以及提升英文阅读能力来阅读专业文献,是持续学习的关键。 论文阅读和GDC资源的获取也至关重要,积累知识,扎实基础,从经典论文和官方教程开始,逐渐扩大视野。 最后,建议多实践,深入理解渲染管线,关注技术美术的Todo和社区分享,持续探索和学习。Unity的URP HDRP等SRP管线详解(包含源码分析)
SRP为可编程渲染管线,Unity中通过C#能自定义多种渲染管线,包含通用管线(URP)与高清管线(HDRP)。
URP通用管线,综合性能与表现力,适合手游或端游场景;HDRP为高清管线,拥有极致表现力,适用于端游、影视制作。
大体结构包括:RenderPipelineAsset、RenderPipelines、Renderer与RenderPass。RenderFeature为辅助组件,配置特定事件并注入到Renderer中的时机进行执行。
具体分析:在RenderPipelineAsset中,创建多条渲染管线。RenderPipelines则构成具体渲染流程,于每一帧调用Render()处理本帧命令,绘制图像。
Renderer维护ScriptableRenderPass列表,每帧通过SetUp()注入Pass执行渲染过程,最终得到序列化结果(ScriptableRendererData)。
RenderPass实现具体渲染逻辑,其Execute()函数执行于每一帧,实现渲染功能。
RenderFeature主要提供“空壳”结构,通过配置RenderPassEvent并注入实例到Renderer中。图文征集源码
总结:理解URP架构,能掌握渲染管线核心。后续将继续分享渲染案例、实用工具等内容。
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中实现。jbd 源码分析首先在Setup函数中将pass添加到队列,执行时,执行队列内的pass,并按顺序提交渲染操作。
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的实现,它支持物理光照、金属度与粗糙度等参数,提供更精确的babel源码转换渲染效果。PBR Shader结构遵循ShaderLab语法,内嵌HLSL Shader编程语言,拥有多种Pass,包括ForwardLit Pass、ShadowCaster Pass等,分别负责3D物体渲染、阴影计算和深度测试等关键步骤。
在光照计算方面,URP PBR Shader通过一系列步骤进行处理,包括初始化双向分布函数BRDF、计算主光源光照、处理全局光照、附加光源光照和自发光等。这种分离式的光照计算方法,使得URP渲染管线在实现高质量渲染效果的同时,优化了性能。
综上所述,URP渲染管线与Unity内置管线在Shader编写、光源处理和光照计算等方面存在明显差异,这些差异为开发者提供了多样化的选择和优化策略。通过深入理解这些差异,开发者能够根据项目需求和性能目标,选择最适合的渲染管线来实现高质量的游戏渲染。
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`。最终效果展示则需通过实际项目测试和优化,以确保阴影效果的稳定性和视觉表现。在实践中,可能遇到的问题需仔细排查和解决,以获得满意的结果。
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)的内部工作原理和源码结构,深入探讨了URP如何实现高效的渲染流程和丰富的渲染特性。首先,我们介绍了UnityEngine.CoreModule和UnityEngine.Rendering.Universal命名空间的基本概念,理解了它们在URP中的角色。然后,通过查找CreatePipeline方法和分析UniversalRenderPipeline实例的内部结构,揭示了URP实例化和初始化的过程。
在渲染管线实例阶段,我们聚焦于UniversalRenderPipeline实例的Render方法,以及它在每帧执行的任务,特别是Profiling器的使用,这为性能优化提供了重要的工具。接着,文章深入探讨了ScriptableRenderer类,它实现了渲染策略,包括剔除、照明以及效果支持的描述,展示了其在渲染过程中如何与摄像机交互。
对于渲染过程的细节,文章详细说明了从设置图形参数、执行剔除、初始化光照、执行渲染Pass到后处理阶段的流程。特别关注了渲染Pass的执行,以及如何通过自定义RenderPass来扩展URP的功能。在渲染结束后,文章还介绍了如何使用ProfilingScope进行性能分析,为优化渲染管线提供了实用的工具。
综上所述,本文以深入的技术细节,全面解析了Unity URP渲染管线的内部机制,旨在帮助开发者更好地理解URP的实现原理,进而优化其应用中的渲染性能。
Unity渲染学习之URP
Unity推出SRP系列已有时日,如今许多开发者都倾向于创建自己的渲染管线或对URP进行魔改。深入了解URP的运行处理方式,对我们今后构建自研渲染管线具有很好的借鉴意义。
本文将简要梳理URP的整个流程,但不会深入探讨某个模块的具体实现,也不会涉及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进行排序、分块,设置一些参数,依次执行每个部分,最后绘制一些小玩意。
本文主要简要介绍了URP的处理流程,让大家了解其组织结构。这样在编写SRP或调试URP时,也能作为参考。URP的核心渲染实现是ScriptableRenderPass,这样的设计方便我们日后添加自己的渲染功能,例如使用Render Feature。以下是URP全家福: