一,unity渲染管线简介
Unity引擎的渲染管线主要分为"渲染核心库"与"渲染策略"两个部分, “渲染核心库”是Unity把基于OpenGL/DirectX把渲染相关的接口函数封装成API,这部分Unity引擎写好后作为核心的API渲染库。”渲染策略”指的是Unity引擎绘制整个游戏场景的时候,如何处理多相机,多光源,阴影投射,物体绘制,雾,自发光等。这个就叫做渲染策略,渲染管线基于一种渲染策略,调用渲染核心库中的API,把整个游戏场景绘制出来。
渲染管线通过执行 剔除、渲染、后处理 来获取场景的内容,并将这些内容显示在屏幕上。不同的渲染管线具有不同的功能和性能特征,并且适用于不同的游戏、应用程序和平台。
- unity提供三种渲染管线,内置渲染管线、通用渲染管线(URP)和高清渲染管线(HDRP),也可以通过unity的可编程渲染管线(Scriptable Render Pipeline,SRP) API 来完全自定义渲染管线。
- 内置渲染管线是unity默认的,自定义选项有限,是向前渲染(支持任意多光源,每个光照各走一遍pass性能差)。(可以用CommandBuffer和回调进行骚操作,版稳定性不好死板)
- URP(Universal Render Pipeline)「前身LWRP–轻量级渲染管线」是用SRP写的非侵入式轻量级自定义渲染管线,专注性能,比如只支持几个光源但能在同一个pass计算;除了有特殊需求选它就对了。
- HDRP可以做更多复杂算法,可以在高端平台上(PC主机等)输出高保真图形,支持全局光照、光线跟踪、子面散射等,但想得到好效果需要大量贴图,人力预算up!「因为这次主要学习URP,HDRP这里就简单了解下。也有人说HDRP太复杂了,不如直接用ue。」
- 其主要区别在于渲染策略,不同的渲染策略对应的shader不一样,之前学习的shader写法都是针对向前渲染的,如果切换成URP则shader包需要重新开发。可编程渲染管线shader语法结构还是shader lab,开发语言使用HLSL,有的也支持shader graphic。
二,通用渲染管线URP
三,shader升级URP
1,Builtin RP和URP中内置Shader 的对应
2,总体结构
- 在SubShader的Tags中添加"RenderPipeline" = “UniversalPipeline"表示该SubShader是给URP用的「HDRP设置为"HDRenderPipeline”」
- 并使用HLSL的宏替代CG:
Built-in | URP |
---|
CGPROGRAM、HLSLPROGRAM | HLSLPROGRAM |
ENDCG、ENDHLSL | ENDHLSL |
CGINCLUDE、HLSLINCLUDE | HLSLINCLUDE |
- HLSL是URP的首选语言,但URP也支持CG语言,因此CGPROGRAM等也能用,就是和SRP Batcher 不兼容。
- 在Properties中声明的属性需要再在HLSL 代码中用CBUFFER声明(为了SRP Batcher):
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
CBUFFER_START(UnityPerMaterial)
half4 _BaseColor;
float4 _BaseMap_ST;
CBUFFER_END
- fixed都不支持了,改为half或者float。
3,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
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);
}
...
}
参考资料
- unity官方文档
- 知乎-Unity URP/SRP 渲染管线浅入深出
- From Built-in to URP
- 内置到URP官方切换文档