荷Java MCP 的鉴权?好简单的啦r
URP定制的流程在这里(从灯光阴影投射、深度和深度法线预渲染、到深度拷贝、延迟渲染中的特别执行的LightMode:”UniversalForwardOnly”、再到延迟渲染的GBuffer及其对GBuffer的屏幕空间的光照处理、不透明阶段Pass、深度拷贝、运动向量Pass、天空盒Pass、透明物体Pass、离屏UIPass、覆盖UIPass、最后的混合、深度拷贝、输出到缓冲区“_Camera
角币裙吐RenderPipeline基类?
通过继承该类并重写Render()方法,开发者可自定义渲染流程调度逻辑,替代传统固定管线。(URP中UniversalRenderPipeline : RenderPipeline 继承并重写Render方法。)
?ScriptableRenderContext?
作为C#脚本与底层图形API的桥梁,允许通过代码调度渲染命令(如剔除、绘制)。(public struct ScriptableRenderContext : IEquatable定义自定义渲染管道使用的状态和绘图命令。)
?管线资源分离机制?
RenderPipelineAsset:存储配置数据(如材质、Shader参数)(URP中是
public partial class UniversalRenderPipelineAsset : RenderPipelineAsset, ISerializationCallbackReceiver)
RenderPipelineInstance:执行实际渲染逻辑的实例类。(在URP中,上面的RenderPipelineAsset资产类中重写protected override RenderPipeline CreatePipeline()方法,在其中创建渲染管线实例var pipeline = new UniversalRenderPipeline(this);)
?关键扩展点?
?事件回调?
通过RenderPipelineManager订阅渲染生命周期事件(如beginContextRendering),在特定阶段注入自定义逻辑。
?动态渲染策略?
支持运行时切换渲染路径(如正向/延迟渲染),适应不同硬件性能需求(这里的渲染路径是URP或HDRP自己实现的,例如Forward+也是,所以这个渲染路径只是实现管线时的自定义渲染策略,所以运行时能切换。但是一般不建议切换,因为各种shader实现时都会根据渲染路径实现相应执行的Pass,如果随便切换,会导致部分shader可能因为只适配某种渲染路径,对其他渲染路径显示渲染异常。)。
URP在SRP上的具体实现?
?资源与实例初始化?
?URP管线资源?(UniversalRenderPipelineAsset):
定义默认Shader、光照模型、后处理栈等参数。
?实例化流程?:
资源创建时调用CreatePipeline()生成UniversalRenderPipeline实例,接管Unity渲染循环。
其中的渲染器基类ScriptableRenderer作为 渲染器可以用于所有摄像机,也可以在每个摄像机的基础上重写。它将实现光剔除和设置,并描述要在帧中执行的ScriptableRenderPass列表。渲染器可以通过额外的scriptablerendererfeature进行扩展,以支持更多的效果。渲染器的资源在ScriptableRendererData中序列化(编辑器中就在这个资源上挂载设置RendererFeature)。
UniversalRenderer 默认的3D渲染器继承自ScriptableRenderer。在其构造函数中
public UniversalRenderer(UniversalRendererData data) : base(data) 根据上述序列化的Data数据,创建默认的渲染Pass逻辑。渲染路径就是在这个类文件中一同定义的,在构造函数中根据不同路径,给出不同策略执行Pass。
定义渲染路径
namespace UnityEngine.Rendering.Universal
{
///
/// Rendering modes for Universal renderer.
///
public enum RenderingMode
{
///
Forward = 0,
///
[InspectorName("Forward+")]
ForwardPlus = 2,
///
Deferred = 1
};
// 省略下面代码。。。
}
构造函数根据渲染路径给出不同Pass执行策略
///
/// Constructor for the Universal Renderer.
///
/// The settings to create the renderer with.
public UniversalRenderer(UniversalRendererData data) : base(data)
{
// Query and cache runtime platform info first before setting up URP.
PlatformAutoDetect.Initialize();
...
设置各种材质和状态
// 设置各种材质和状态
#if ENABLE_VR && ENABLE_XR_MODULE
Experimental.Rendering.XRSystem.Initialize(XRPassUniversal.Create, data.xrSystemData.shaders.xrOcclusionMeshPS, data.xrSystemData.shaders.xrMirrorViewPS);
#endif
m_BlitMaterial = CoreUtils.CreateEngineMaterial(data.shaders.coreBlitPS);
m_BlitHDRMaterial = CoreUtils.CreateEngineMaterial(data.shaders.blitHDROverlay);
m_CopyDepthMaterial = CoreUtils.CreateEngineMaterial(data.shaders.copyDepthPS);
m_SamplingMaterial = CoreUtils.CreateEngineMaterial(data.shaders.samplingPS);
m_StencilDeferredMaterial = CoreUtils.CreateEngineMaterial(data.shaders.stencilDeferredPS);
m_CameraMotionVecMaterial = CoreUtils.CreateEngineMaterial(data.shaders.cameraMotionVector);
m_ObjectMotionVecMaterial = CoreUtils.CreateEngineMaterial(data.shaders.objectMotionVector);
StencilStateData stencilData = data.defaultStencilState;
m_DefaultStencilState = StencilState.defaultValue;
m_DefaultStencilState.enabled = stencilData.overrideStencilState;
m_DefaultStencilState.SetCompareFunction(stencilData.stencilCompareFunction);
m_DefaultStencilState.SetPassOperation(stencilData.passOperation);
m_DefaultStencilState.SetFailOperation(stencilData.failOperation);
m_DefaultStencilState.SetZFailOperation(stencilData.zFailOperation);
m_IntermediateTextureMode = data.intermediateTextureMode;
if (UniversalRenderPipeline.asset?.supportsLightCookies ?? false)
{
var settings = LightCookieManager.Settings.Create();
var asset = UniversalRenderPipeline.asset;
if (asset)
{
settings.atlas.format = asset.additionalLightsCookieFormat;
settings.atlas.resolution = asset.additionalLightsCookieResolution;
}
m_LightCookieManager = new LightCookieManager(ref settings);
}
this.stripShadowsOffVariants = true;
this.stripAdditionalLightOffVariants = true;
#if ENABLE_VR && ENABLE_VR_MODULE
#if PLATFORM_WINRT || PLATFORM_ANDROID
// AdditionalLightOff variant is available on HL&Quest platform due to performance consideration.
this.stripAdditionalLightOffVariants = !PlatformAutoDetect.isXRMobile;
#endif
#endif
Forward和Forward+灯光准备,深度预处理、深度拷贝模式等设置。
ForwardLights.InitParams forwardInitParams;
forwardInitParams.lightCookieManager = m_LightCookieManager;
forwardInitParams.forwardPlus = data.renderingMode == RenderingMode.ForwardPlus;
m_Clustering = data.renderingMode == RenderingMode.ForwardPlus;
m_ForwardLights = new ForwardLights(forwardInitParams);
//m_DeferredLights.LightCulling = data.lightCulling;
this.m_RenderingMode = data.renderingMode;
this.m_DepthPrimingMode = data.depthPrimingMode;
this.m_CopyDepthMode = data.copyDepthMode;
#if UNITY_ANDROID || UNITY_IOS || UNITY_TVOS
this.m_DepthPrimingRecommended = false;
#else
this.m_DepthPrimingRecommended = true;
#endif
关键来了!URP定制的流程在这里(从灯光阴影投射、深度和深度法线预渲染、到深度拷贝、延迟渲染中的特别执行的LightMode:”UniversalForwardOnly”、再到延迟渲染的GBuffer及其对GBuffer的屏幕空间的光照处理、不透明阶段Pass、深度拷贝、运动向量Pass、天空盒Pass、透明物体Pass、离屏UIPass、覆盖UIPass、最后的混合、深度拷贝、输出到缓冲区“_CameraColorAttachment”)
// Note: Since all custom render passes inject first and we have stable sort,
// we inject the builtin passes in the before events.
m_MainLightShadowCasterPass = new MainLightShadowCasterPass(RenderPassEvent.BeforeRenderingShadows);
m_AdditionalLightsShadowCasterPass = new AdditionalLightsShadowCasterPass(RenderPassEvent.BeforeRenderingShadows);
#if ENABLE_VR && ENABLE_XR_MODULE
m_XROcclusionMeshPass = new XROcclusionMeshPass(RenderPassEvent.BeforeRenderingOpaques);
// Schedule XR copydepth right after m_FinalBlitPass
m_XRCopyDepthPass = new CopyDepthPass(RenderPassEvent.AfterRendering + k_AfterFinalBlitPassQueueOffset, m_CopyDepthMaterial);
#endif
m_DepthPrepass = new DepthOnlyPass(RenderPassEvent.BeforeRenderingPrePasses, RenderQueueRange.opaque, data.opaqueLayerMask);
m_DepthNormalPrepass = new DepthNormalOnlyPass(RenderPassEvent.BeforeRenderingPrePasses, RenderQueueRange.opaque, data.opaqueLayerMask);
if (renderingModeRequested == RenderingMode.Forward || renderingModeRequested == RenderingMode.ForwardPlus)
{
m_PrimedDepthCopyPass = new CopyDepthPass(RenderPassEvent.AfterRenderingPrePasses, m_CopyDepthMaterial, true);
}
if (this.renderingModeRequested == RenderingMode.Deferred)
{
var deferredInitParams = new DeferredLights.InitParams();
deferredInitParams.stencilDeferredMaterial = m_StencilDeferredMaterial;
deferredInitParams.lightCookieManager = m_LightCookieManager;
m_DeferredLights = new DeferredLights(deferredInitParams, useRenderPassEnabled);
m_DeferredLights.AccurateGbufferNormals = data.accurateGbufferNormals;
m_GBufferPass = new GBufferPass(RenderPassEvent.BeforeRenderingGbuffer, RenderQueueRange.opaque, data.opaqueLayerMask, m_DefaultStencilState, stencilData.stencilReference, m_DeferredLights);
// Forward-only pass only runs if deferred renderer is enabled.
// It allows specific materials to be rendered in a forward-like pass.
// We render both gbuffer pass and forward-only pass before the deferred lighting pass so we can minimize copies of depth buffer and
// benefits from some depth rejection.
// - If a material can be rendered either forward or deferred, then it should declare a UniversalForward and a UniversalGBuffer pass.
// - If a material cannot be lit in deferred (unlit, bakedLit, special material such as hair, skin shader), then it should declare UniversalForwardOnly pass
// - Legacy materials have unamed pass, which is implicitely renamed as SRPDefaultUnlit. In that case, they are considered forward-only too.
// TO declare a material with unnamed pass and UniversalForward/UniversalForwardOnly pass is an ERROR, as the material will be rendered twice.
StencilState forwardOnlyStencilState = DeferredLights.OverwriteStencil(m_DefaultStencilState, (int)StencilUsage.MaterialMask);
ShaderTagId[] forwardOnlyShaderTagIds = new ShaderTagId[]
{
new ShaderTagId("UniversalForwardOnly"),
new ShaderTagId("SRPDefaultUnlit"), // Legacy shaders (do not have a gbuffer pass) are considered forward-only for backward compatibility
new ShaderTagId("LightweightForward") // Legacy shaders (do not have a gbuffer pass) are considered forward-only for backward compatibility
};
int forwardOnlyStencilRef = stencilData.stencilReference | (int)StencilUsage.MaterialUnlit;
m_GBufferCopyDepthPass = new CopyDepthPass(RenderPassEvent.BeforeRenderingGbuffer + 1, m_CopyDepthMaterial, true);
m_DeferredPass = new DeferredPass(RenderPassEvent.BeforeRenderingDeferredLights, m_DeferredLights);
m_RenderOpaqueForwardOnlyPass = new DrawObjectsPass("Render Opaques Forward Only", forwardOnlyShaderTagIds, true, RenderPassEvent.BeforeRenderingOpaques, RenderQueueRange.opaque, data.opaqueLayerMask, forwardOnlyStencilState, forwardOnlyStencilRef);
}
// Always create this pass even in deferred because we use it for wireframe rendering in the Editor or offscreen depth texture rendering.
m_RenderOpaqueForwardPass = new DrawObjectsPass(URPProfileId.DrawOpaqueObjects, true, RenderPassEvent.BeforeRenderingOpaques, RenderQueueRange.opaque, data.opaqueLayerMask, m_DefaultStencilState, stencilData.stencilReference);
m_RenderOpaqueForwardWithRenderingLayersPass = new DrawObjectsWithRenderingLayersPass(URPProfileId.DrawOpaqueObjects, true, RenderPassEvent.BeforeRenderingOpaques, RenderQueueRange.opaque, data.opaqueLayerMask, m_DefaultStencilState, stencilData.stencilReference);
bool copyDepthAfterTransparents = m_CopyDepthMode == CopyDepthMode.AfterTransparents;
RenderPassEvent copyDepthEvent = copyDepthAfterTransparents ? RenderPassEvent.AfterRenderingTransparents : RenderPassEvent.AfterRenderingSkybox;
m_CopyDepthPass = new CopyDepthPass(
copyDepthEvent,
m_CopyDepthMaterial,
shouldClear: true,
copyResolvedDepth: RenderingUtils.MultisampleDepthResolveSupported() && SystemInfo.supportsMultisampleAutoResolve && copyDepthAfterTransparents);
// Motion vectors depend on the (copy) depth texture. Depth is reprojected to calculate motion vectors.
m_MotionVectorPass = new MotionVectorRenderPass(copyDepthEvent + 1, m_CameraMotionVecMaterial, m_ObjectMotionVecMaterial, data.opaqueLayerMask);
m_DrawSkyboxPass = new DrawSkyboxPass(RenderPassEvent.BeforeRenderingSkybox);
m_CopyColorPass = new CopyColorPass(RenderPassEvent.AfterRenderingSkybox, m_SamplingMaterial, m_BlitMaterial);
#if ADAPTIVE_PERFORMANCE_2_1_0_OR_NEWER
if (needTransparencyPass)
#endif
{
m_TransparentSettingsPass = new TransparentSettingsPass(RenderPassEvent.BeforeRenderingTransparents, data.shadowTransparentReceive);
m_RenderTransparentForwardPass = new DrawObjectsPass(URPProfileId.DrawTransparentObjects, false, RenderPassEvent.BeforeRenderingTransparents, RenderQueueRange.transparent, data.transparentLayerMask, m_DefaultStencilState, stencilData.stencilReference);
}
m_OnRenderObjectCallbackPass = new InvokeOnRenderObjectCallbackPass(RenderPassEvent.BeforeRenderingPostProcessing);
m_DrawOffscreenUIPass = new DrawScreenSpaceUIPass(RenderPassEvent.BeforeRenderingPostProcessing, true);
m_DrawOverlayUIPass = new DrawScreenSpaceUIPass(RenderPassEvent.AfterRendering + k_AfterFinalBlitPassQueueOffset, false); // after m_FinalBlitPass
{
var postProcessParams = PostProcessParams.Create();
postProcessParams.blitMaterial = m_BlitMaterial;
postProcessParams.requestHDRFormat = GraphicsFormat.B10G11R11_UFloatPack32;
var asset = UniversalRenderPipeline.asset;
if (asset)
postProcessParams.requestHDRFormat = UniversalRenderPipeline.MakeRenderTextureGraphicsFormat(asset.supportsHDR, asset.hdrColorBufferPrecision, false);
m_PostProcessPasses = new PostProcessPasses(data.postProcessData, ref postProcessParams);
}
m_CapturePass = new CapturePass(RenderPassEvent.AfterRendering);
m_FinalBlitPass = new FinalBlitPass(RenderPassEvent.AfterRendering + k_FinalBlitPassQueueOffset, m_BlitMaterial, m_BlitHDRMaterial);
#if UNITY_EDITOR
m_FinalDepthCopyPass = new CopyDepthPass(RenderPassEvent.AfterRendering + 9, m_CopyDepthMaterial);
#endif
// RenderTexture format depends on camera and pipeline (HDR, non HDR, etc)
// Samples (MSAA) depend on camera and pipeline
m_ColorBufferSystem = new RenderTargetBufferSystem("_CameraColorAttachment");
最后最一些兼容操作,结束构造。完成URP基本管线的主体流程。
supportedRenderingFeatures = new RenderingFeatures();
if (this.renderingModeRequested == RenderingMode.Deferred)
{
// Deferred rendering does not support MSAA.
this.supportedRenderingFeatures.msaa = false;
// Avoid legacy platforms: use vulkan instead.
unsupportedGraphicsDeviceTypes = new GraphicsDeviceType[]
{
GraphicsDeviceType.OpenGLCore,
GraphicsDeviceType.OpenGLES2,
GraphicsDeviceType.OpenGLES3
};
}
LensFlareCommonSRP.mergeNeeded = 0;
LensFlareCommonSRP.maxLensFlareWithOcclusionTemporalSample = 1;
LensFlareCommonSRP.Initialize();
m_VulkanEnablePreTransform = GraphicsSettings.HasShaderDefine(BuiltinShaderDefine.UNITY_PRETRANSFORM_TO_DISPLAY_ORIENTATION);
}
?核心渲染流程分解?
URP将渲染分为五个阶段,均在Render()方法中调度:
?阶段? ?URP实现细节?
?准备阶段? 收集场景渲染对象与光源数据,配置相机参数与目标纹理。
?几何阶段? 执行视锥剔除,生成GPU顶点数据;通过ScriptableRenderContext.DrawRenderers提交绘制命令。
?光照阶段? 采用简化PBR模型:计算实时光源贡献,支持烘焙光照混合;动态光源采用Tile-Based优化策略(Forward+路径时)。
?光栅化阶段? 执行深度预通道(Depth Prepass)减少过度绘制,结合GPU Instancing优化批次处理。
?后处理阶段? 在独立Pass中应用抗锯齿(FXAA/TAA)、Bloom等效果,支持自定义RendererFeature扩展。
?性能优化关键技术?
?SRP Batcher?:对相同Shader变体但不同材质的物体进行动态合批,显著降低SetPass Call。
?光照剔除优化?:按层级控制剔除距离(layerCullDistances),对静态物体预计算遮挡数据。
URP对SRP的扩展与简化?
?标准化功能封装?
内置轻量级PBR光照模型,取代HDRP的复杂物理模拟以提升跨平台性能。
集成?Shader Graph?可视化工具链,降低着色器开发门槛。(后期版本内置管线也可用ShaderGraph了)
?跨平台适配策略?
动态切换渲染精度(如移动端禁用实时阴影),通过QualitySettings分级配置。
资源包精简:剔除HDRP的高精度贴图与计算密集型特效,缩小运行时内存占用。
对URP的扩展
URP基本管线流程在UniversalRenderer的构造函数中已经定义完整。并且在其中每个阶段都给出了插入点。那么只需要在这些插入点用创建RendererFeature的方式插入自定义的Pass来影响和扩充基本的URP管线。
还有一种方式用RenderPipelineManager 提供的点位插入自定义Pass。
更多推荐
所有评论(0)