Unity 内置渲染管线转URP
一、CG 替換 HLSL
未使用光照計算的shader升級后不做修改仍然可以使用,但是可能會不兼容SRP Batcher,所以仍然需要修改,使用了光照計算的shader必須要修改。
SubShader的Tags中增加 “RenderPipeline”="UniversalPipeline"聲明
要保證多pass物體正確繪制,需要確保有個pass打上 UniversalForward 的tag,其余pass有 SRPDefaultUnlit的tag也行,沒有也行。
HLSLPROGRAM 替換 CGPROGRAM
HLSLINCLUDE 替換 INCLUDE
ENDHLSL 替換 ENDCG
fixed 替換為:half 或者 float
FallBack
FallBack “Hidden/Universal Render Pipeline/FallbackError”
LightMode
"LightMode" 要改為URP支持的模式, 比如 "LightMode" = "Forward" 替換為 "LightMode" = "UniversalForward"其他常用URP的mode類型:"LightMode" = "Universal2D""LightMode" = "Meta""LightMode" = "DepthOnly""LightMode" = "ShadowCaster"使用URP ShaderLibrary引用Core.hlsl替換內置渲染管線中的UnityCG.cginc
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 替換 #include "UnityCG.cginc"其他庫類似:
#include "Lighting.HLSLinc" 替換為: #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl"陰影: #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"內置結構體、內置函數 和矩陣
appdata_full 這種結構體不能用了,如何一一替換我就不舉例了
內置函數 和矩陣需要查閱Packages/Universal RP/ShaderLibrary/UnityInput
內置結構體、函數需要查閱
Packages/Universal RP/ShaderLibrary/Input
Packages/Universal RP/ShaderLibrary/Core
使用 TransformObjectToHClip 替換 UnityObjectToClipPos
或者改成如下寫法:
GetVertexPositionInputs 計算不同坐標系中的位置,結果包含世界坐標系坐標,觀察坐標系坐標,裁剪坐標系坐標,標準設備坐標系坐標,未使用到的坐標不會被包含到編譯出的shader中,所以不會有額外的不必要的計算量。TRANSFORM_TEX 在內置渲染管線和URP中都可以用。GetVertexNormalInputs 可以將法線和切線從對象坐標系變換到世界坐標系。也可以用 TransformObjectToWorldNormal(IN.normalOS) 代替。
VertexNormalInputs normalInputs = GetVertexNormalInputs(IN.normalOS, IN.tangentOS);
在URP中紋理和采樣器的定義改成如下寫法:
// 將_BaseMap聲明為Texture2D對象TEXTURE2D(_MainTex);// 將_BaseMap聲明為Texture2D對象SAMPLER(sampler_MainTex);float4 frag (v2f i) : SV_Target{float4 col = SAMPLE_TEXTURE2D(_BaseMap,sampler_BaseMap, i.texcoord);return col;}區分 multi_compile 和 shader_feature,剝離不需要的編譯選項,減少shader變體。
https://zhuanlan.zhihu.com/p/77043332
https://www.jianshu.com/p/8750704a2f4c
URP不支持表面著色器,URP ShaderLibrary 中處理光照計算的函數在 Lighting.hlsl中,該文件需要手動include。
//這些編譯指令用于接收陰影 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _SHADOWS_SOFT#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"當使用Lighting.hlsl支持光照和陰影,應該添加下面的編譯選項,如果沒有定義,ShaderLibrary會跳過一些計算。
// Main Light Shadows #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE// Additional Lights & Shadows #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS// Soft Shadows #pragma multi_compile _ _SHADOWS_SOFT// Other (Mixed lighting, baked lightmaps, fog) #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile_fog// Supporting shadows will also require passing a positionWS, // and shadowCoord into the fragment shader, again you'll have // to see the Lighting sections for actual examples.接受投影:
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADEfloat4 frag (v2f i) : SV_Target {float4 shadowCoords = TransformWorldToShadowCoord(i.worldPos);Light mainLight = GetMainLight(shadowCoords);//陰影實時遮擋half shadow = mainLight.shadowAttenuation;return shadow; } 被投影: //新加一個passUsePass "Universal Render Pipeline/Lit/ShadowCaster"為了處理霧,使用ComputeFogFactor 和 MixFog 函數。
#pragma multi_compile_fogstruct Varyings {...half fogFactor : TEXCOORD5;// or whatever unused texcoord// if none are unused pack it together with a half3 or something } ...// In the vertex shader : half fogFactor = ComputeFogFactor(positionInputs.positionCS.z);// In the fragment, just before returning the color : color.rgb = MixFog(color.rgb, IN.fogFactor);二、多Pass問題:
在URP中是使用的single-pass前向渲染,也就是單Pass。
轉URP的時候我們會發現 以前多Pass的shader會異常,只會渲染第一個Pass。
如果我們確實需要多Pass怎么辦?
我們可以通過設置第一個Pass的LightMode為:UniversalForward就行了。
例如:
Shader "lcl/Shader" { Properties { _Color("Color", Color) = (1,1,1,1)_MainTex("Albedo", 2D) = "white" {} } SubShader {LOD 100Lighting OffPass{Tags { "LightMode"="UniversalForward"}...}Pass { Tags {"LightMode"="SRPDefaultUnlit"}...} }但是不推薦多Pass渲染,因為會打斷 SRP Batcher,使DrawCall增加。(當然 如果沒使用SRP Batcher則不影響)
具體什么是SRP Batcher可以參考這里
https://zhuanlan.zhihu.com/p/165574008
https://zhuanlan.zhihu.com/p/165388825
·如果確實需要可以通過RendererFeatures實現多Pass效果
三、兼容SRP Batcher:
首先需要勾選 SRP Batcher。
shader代碼修改:
Shader中所有的內置屬性例如unity_ObjectToWorld,unity_SHAr等,都要在一個名為UnityPerDraw的CBUFFER中聲明;
所有的Material屬性都要在一個名為UnityPerMaterial的CBUFFER中聲明。
例如:
Properties { _Color1 ("Color 1", Color) = (1,1,1,1) _Color2 ("Color 2", Color) = (1,1,1,1) }//原本的寫法 //float4 _Color1; //float4 _Color2;//兼容SRP Batcher的寫法 CBUFFER_START(UnityPerMaterial) float4 _Color1; float4 _Color2; CBUFFER_ENDCBUFFER_START(UnityPerDraw)float4x4 unity_ObjectToWorld; CBUFFER_END如果shader報錯:Shader error in ‘Unlit/SampleUnlit’: redefinition of ‘unity_ObjectToWorld’,重復定義,如果自己的shader代碼里面沒有,那么就是引入了其他的庫文件里面包含了該變量。
最后,我們看Shader的面板,如果出現了類似的提示:
則表示 該屬性 未包含在 CBUFFER_START(UnityPerMaterial) 里面。
注意:如果Shader使用了多Pass渲染,則會打斷 SRP Batcher。
參考鏈接:
https://zhuanlan.zhihu.com/p/254810253
https://blog.csdn.net/wannaconquer/article/details/114092927
總結
以上是生活随笔為你收集整理的Unity 内置渲染管线转URP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux驱动开发中与设备树相关的6种d
- 下一篇: IAR 8.3 for Arm 安装与注