unity渲染管线及升级URP

  • 22.5.31 发现这篇只能查找参考用,实际改urp看了用处不大,urp管线下pbrshader流程看新写的URP实现PBR shader

一,unity渲染管线简介

Unity引擎的渲染管线主要分为"渲染核心库"与"渲染策略"两个部分, “渲染核心库”是Unity把基于OpenGL/DirectX把渲染相关的接口函数封装成API,这部分Unity引擎写好后作为核心的API渲染库。”渲染策略”指的是Unity引擎绘制整个游戏场景的时候,如何处理多相机,多光源,阴影投射,物体绘制,雾,自发光等。这个就叫做渲染策略,渲染管线基于一种渲染策略,调用渲染核心库中的API,把整个游戏场景绘制出来。

渲染管线通过执行 剔除、渲染、后处理 来获取场景的内容,并将这些内容显示在屏幕上。不同的渲染管线具有不同的功能和性能特征,并且适用于不同的游戏、应用程序和平台。

  • unity提供三种渲染管线,内置渲染管线、通用渲染管线(URP)和高清渲染管线(HDRP),也可以通过unity的可编程渲染管线(Scriptable Render Pipeline,SRP) API 来完全自定义渲染管线。
    1. 内置渲染管线是unity默认的,自定义选项有限,是向前渲染(支持任意多光源,每个光照各走一遍pass性能差)。(可以用CommandBuffer和回调进行骚操作,版稳定性不好死板)
    2. URP(Universal Render Pipeline)「前身LWRP–轻量级渲染管线」是用SRP写的非侵入式轻量级自定义渲染管线,专注性能,比如只支持几个光源但能在同一个pass计算;除了有特殊需求选它就对了。
    3. HDRP可以做更多复杂算法,可以在高端平台上(PC主机等)输出高保真图形,支持全局光照、光线跟踪、子面散射等,但想得到好效果需要大量贴图,人力预算up!「因为这次主要学习URP,HDRP这里就简单了解下。也有人说HDRP太复杂了,不如直接用ue。」

在这里插入图片描述

  • 其主要区别在于渲染策略,不同的渲染策略对应的shader不一样,之前学习的shader写法都是针对向前渲染的,如果切换成URP则shader包需要重新开发。可编程渲染管线shader语法结构还是shader lab,开发语言使用HLSL,有的也支持shader graphic。

二,通用渲染管线URP

  • URP相对内置管线的优点:

    1. 开源。
    2. 渲染路径为单Pass Forward Rendering,DrawCall数量大大下降(支持动态灯光数量受GPU限制),阴影处理性能也好很多。(内置多光源时需要FowardAdd Pass,因此以前后用烘焙light map)
    3. 拓展性好,拓展入口相当于CommandBuffer的可视化操作;新设计取代了GrabPass结构,可以提供Opaque Texture。
    4. SRP Batcher,对shader的批处理,只要着色器变体一样的都一起批处理。并将shader材质数据保存在Gpu中用时绑定,而不是每次用时从缓冲区上传,以此减少渲染状态设置的CPU开销—比如glUniform4fv等设置。「变体是指shader中通过关键字设置的不同逻辑功能或者shader设置参数不同的,就是不同变体」
  • 与默认管线功能对比见URP与内置渲染管线功能对照表

  • URP与unity版本对应:
    在这里插入图片描述

三,shader升级URP

1,Builtin RP和URP中内置Shader 的对应

在这里插入图片描述

2,总体结构

  1. 在SubShader的Tags中添加"RenderPipeline" = “UniversalPipeline"表示该SubShader是给URP用的「HDRP设置为"HDRenderPipeline”」
  2. 并使用HLSL的宏替代CG:
Built-in URP
CGPROGRAM、HLSLPROGRAM HLSLPROGRAM
ENDCG、ENDHLSL ENDHLSL
CGINCLUDE、HLSLINCLUDE HLSLINCLUDE
  • HLSL是URP的首选语言,但URP也支持CG语言,因此CGPROGRAM等也能用,就是和SRP Batcher 不兼容。
  1. 在Properties中声明的属性需要再在HLSL 代码中用CBUFFER声明(为了SRP Batcher):
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);

CBUFFER_START(UnityPerMaterial)
    half4 _BaseColor;
    float4 _BaseMap_ST;
CBUFFER_END
  1. fixed都不支持了,改为half或者float。

3,include

  • include对应:
\ Built-in URP
Core Unity.cginc Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl
Light AutoLight.cginc Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl
Shadows AutoLight.cginc Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl
Surface shaders Lighting.cginc URP内没有,可以参考该github项目
  • 示例
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  • URP其他常用include:SpaceTransforms.hlsl、ShaderVariablesFunctions.hlsl、Common.hlsl、Input.hlsl、Color.hlsl、DeclareDepthTexture.hlsl、DeclareOpaqueTextue.hlsl
  • Core.hlsl可以直接引用,UnityInput.hlsl、UnityInstancing.hlsl、SpaceTransforms.hlsl等需要带上前缀,防止重定义。

4,光照模式LightMode

  • Builtin RP和URP对应的光照模式:
Built-in URP
ForwardBase UniversalForward
ForwardAdd 移除,开启关键字_ADDITIONAL_LIGHTS解决
Deferred 以及相关 URP12.0支持
Vertex and related 移除
ShadowCaster ShadowCaster
MotionVectors 暂不支持
  • URP新增的:DepthOnly、Meta(用于烘焙光照贴图)、Universal2D(用于2D的前向渲染)、UniversalGBuffer(延迟渲染用)、UniversalForwardOnly(延迟渲染中表示该pass用向前渲染)。

5,变体Variants

  • 类似内置管线用multi_compile_fwdbase编译ForwardBasePass;URP涉及批处理的变体,可以用#pragma multi_compile添加关键字设置:
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE

6,预定义宏

辅助宏

Built-in URP
UNITY_PROJ_COORD(a) 移除,改用 a.xy/a.w
UNITY_INITIALIZE_OUTPUT(type, name) ZERO_INITIALIZE(type, name)

阴影贴图

参考Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl

Built-in URP
UNITY_DECLARE_SHADOWMAP(tex) TEXTURE2D_SHADOW_PARAM(textureName, samplerName)
UNITY_SAMPLE_SHADOW(tex, uv) SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3)
UNITY_SAMPLE_SHADOW_PROJ(tex, uv) SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord4.xyz/coord4.w)
UNITY_SHADOW_COORDS(x) float4 shadowCoord : TEXCOORD##x
TRANSFER_SHADOW(a) a.shadowCoord = TransformWorldToShadowCoord(worldSpacePosition)
SHADOWS_SCREEN 移除了

纹理采样器声明

Built-in URP
UNITY_DECLARE_TEX2D(name) TEXTURE2D(textureName); SAMPLER(samplerName);
UNITY_DECLARE_TEX2D_NOSAMPLER(name) TEXTURE2D(textureName);
UNITY_DECLARE_TEX2DARRAY(name) TEXTURE2D_ARRAY(textureName); SAMPLER(samplerName);
UNITY_SAMPLE_TEX2D(name, uv) SAMPLE_TEXTURE2D(textureName, samplerName, coord2)
UNITY_SAMPLE_TEX2D_SAMPLER(name, samplername, uv) SAMPLE_TEXTURE2D(textureName, samplerName, coord2)
UNITY_SAMPLE_TEX2DARRAY(name, uv) SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index)
UNITY_SAMPLE_TEX2DARRAY_LOD(name, uv, lod) SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod)
UNITY_INITIALIZE_OUTPUT(name) ZERO_INITIALIZE(name)

光照、雾

Built-in URP
UNITY_LIGHTMODEL_AMBIENT half3(unity_SHAr.w,unity_SHAr.w,unity_SHAr.w);
UNITY_FOG_COORDS(x) 用float fogCoord : TEXCOORD##x;
UNITY_TRANSFER_FOG(o, outpos) o.fogCoord = ComputeFogFactor(clipSpacePosition.z);
UNITY_APPLY_FOG(coord, col) color = MixFog(color, i.fogCoord);

7,辅助函数

变换函数

Built-in URP
float4 UnityObjectToClipPos(float3 pos) float4 TransformObjectToHClip(float3 positionOS)
float4 UnityWorldToClipPos(float3 pos) float4 TransformWorldToHClip(float3 positionWS)
float3 UnityObjectToViewPos(float3 pos) TransformWorldToView(TransformObjectToWorld(positionOS))
float3 UnityObjectToWorldNormal(in float3 norm) float3 TransformObjectToWorldNormal(float3 normalOS,bool doNormalize = true)
float3 UnityWorldSpaceViewDir (float4 v) _WorldSpaceCameraPos.xyz - positionWS
float3 UnityObjectToWorldDir (float4 v) float3 TransformObjectToWorldDir(real3 dirOS)

通用辅助函数

Built-in URP
float3 ObjSpaceViewDir (float4 v) TransformWorldToObject(GetCameraPositionWS()) - objectSpacePosition;
float2 ParallaxOffset (half h, half height, half3 viewDir) 移除了。可以从UnityCG.cginc复制过来
fixed Luminance (fixed3 c) real Luminance(real3 linearRgb)
fixed3 DecodeLightmap (fixed4 color) real3 DecodeLightmap(real4 encodedIlluminance, real4 decodeInstructions)
float4 EncodeFloatRGBA (float v) 移除了。可以从UnityCG.cginc复制过来
float DecodeFloatRGBA (float4 enc) 移除了。可以从UnityCG.cginc复制过来
float2 EncodeFloatRG (float v) 移除了。可以从UnityCG.cginc复制过来
float DecodeFloatRG (float2 enc) 移除了。可以从UnityCG.cginc复制过来
float2 EncodeViewNormalStereo (float3 n) 移除了。可以从UnityCG.cginc复制过来
float3 DecodeViewNormalStereo (float4 enc4) 移除了。可以从UnityCG.cginc复制过来

向前渲染函数

Built-in URP
float3 WorldSpaceLightDir(float4 v) _MainLightPosition.xyz - TransformObjectToWorld(objectSpacePosition)
float3 ObjSpaceLightDir (float4 v) TransformWorldToObject(_MainLightPosition.xyz) - objectSpacePosition
float3 Shade4PointLights (…) 用half3 VertexLighting(float3 positionWS, half3 normalWS)

屏幕空间

Built-in URP
float4 ComputeScreenPos (float4 clipPos) float4 ComputeScreenPos(float4 positionCS)
float4 ComputeGrabScreenPos (float4 clipPos) 移除了

顶点光照

Built-in URP
float3 ShadeVertexLights (float4 vertex, float3 normal) 用half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w) + VertexLighting(…)

深度

可直接使用 _CameraDepthTexture来采样深度纹理,也可使用SampleSceneDepth(…) 和 LoadSceneDepth(…)来采样。

Built-in URP
LinearEyeDepth (sceneZ) LinearEyeDepth(sceneZ, _ZBufferParams)
Linear01Depth (sceneZ) Linear01Depth(sceneZ, _ZBufferParams)

其他

Built-in URP
shadeSH9 (float4 normal) SampleSH(normal)
unity_ColorSpaceLuminance 用Luminance()

7,内置变量

Built-in URP
_LightColor0 _MainLightColor
_WorldSpaceLightPos0 _MainLightPosition
_LightMatrix0 移除了。目前尚不支持
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0 在URP中,其他光源存储在数组/缓冲区中(取决于平台)。使用Light GetAdditionalLight(uint i, float3 positionWS)获取光源信息
unity_4LightAtten0 同上
unity_LightColor 同上)
unity_WorldToShadow float4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1] 或者_AdditionalLightsWorldToShadow[MAX_VISIBLE_LIGHTS]

使用循环所有其他灯光–GetAdditionalLight(),查询其他灯光计数–GetAdditionalLightsCount()。

8,后处理

  • URP不支持OnPreCull,OnPreRender,OnPostRender和OnRenderImage。
  • 支持OnRenderObject和OnWillRenderObject,但旧管线直接用有问题,需要改写。
  • UPR函数+示例:
beginCameraRendering(ScriptableRenderContext context, Camera camera)
endCameraRendering(ScriptableRenderContext context, Camera camera)
beginFrameRendering(ScriptableRenderContext context,Camera[] cameras)
endFrameRendering(ScriptableRenderContext context,Camera[] cameras)
void OnEnable()
{
    
    
    RenderPipelineManager.beginCameraRendering += MyCameraRendering;
}

void OnDisable()
{
    
    
    RenderPipelineManager.beginCameraRendering -= MyCameraRendering;
}

void MyCameraRendering(ScriptableRenderContext context, Camera camera)
{
    
    
    ...
    if(camera == myEffectCamera)
    {
    
    
    ...
    UniversalRenderPipeline.RenderSingleCamera(context, camera);
    }
    ...
}

参考资料

  1. unity官方文档
  2. 知乎-Unity URP/SRP 渲染管线浅入深出
  3. From Built-in to URP
  4. 内置到URP官方切换文档

猜你喜欢

转载自blog.csdn.net/yx314636922/article/details/124604783