內(nèi)置管線Shader升級到URP詳細手冊

本文基于Unity2020.2,URP10,更新于20210303

本文初版內(nèi)容翻譯自:https://teodutra.com/unity/shaders/urp/graphics/2020/05/18/From-Built-in-to-URP/

譯者:大智
后續(xù)補充:大智

內(nèi)置管線Shader升級到URP詳細手冊

總體結(jié)構(gòu)

1、在SubShader的Tags中添加"RenderPipeline" = "UniversalPipeline"
2、所有URP著色器都是HLSL編寫的,使用宏HLSL包含的shader代碼
3、使用HLSLINCLUDE替代CGINCLUDE

內(nèi)置管線 URP
CGPROGRAM HLSLPROGRAM HLSL程序
ENDCG ENDHLSL ENDHLSL
CGINCLUDE HLSLINCLUDE HLSLINCLUDE

Include文件

內(nèi)容 內(nèi)置管線 URP
Core UnityCG.cginc Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl
Light AutoLight.cginc Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl
Shadow AutoLight.cginc Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl
表面著色器 Lighting.cginc URP內(nèi)沒有,可以參考項目:在此處

其他有用的包括:

燈光模式LightMode

內(nèi)置管線 URP
ForwardBase UniversalForward
ForwardAdd 移除
Deferred以及相關(guān) 尚未支持
Vertex及相關(guān) 移除
ShadowCaster ShadowCaster
MotionVectors 尚未支持

支持的其他照明模式包括:

  • DepthOnly
  • Meta (for lightmap baking)
  • Universal2D

變體Variants

URP支持某些變體,因此,根據(jù)你使用的功能,可能需要使用#pragma multi_compile添加一些關(guān)鍵字:

  • _MAIN_LIGHT_SHADOWS
  • _MAIN_LIGHT_SHADOWS_CASCADE
  • _ADDITIONAL_LIGHTS_VERTEX
  • _ADDITIONAL_LIGHTS
  • _ADDITIONAL_LIGHT_SHADOWS
  • _SHADOWS_SOFT
  • _MIXED_LIGHTING_SUBTRACTIVE

預(yù)定義的著色器宏

輔助宏

內(nèi)置管線 URP
UNITY_PROJ_COORD(a) 移除了,使用a.xy / a.w代替
UNITY_INITIALIZE_OUTPUT(type,name) ZERO_INITIALIZE(type,name)

陰影貼圖

必須include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl”

內(nèi)置管線 URP
UNITY_DECLARE_SHADOWMAPtex TEXTURE2D_SHADOW_PARAMtextureNamesamplerName
UNITY_SAMPLE_SHADOWtex,uv SAMPLE_TEXTURE2D_SHADOWtextureNamesamplerName,coord3
UNITY_SAMPLE_SHADOW_PROJtex,uv SAMPLE_TEXTURE2D_SHADOWtextureName,samplerName,coord4.xyz/coord4.w

紋理/采樣器聲明宏

Unity有很多紋理/采樣器宏來改善API之間的交叉兼容性,但是人們并不習(xí)慣使用它們。URP中這些宏的名稱有所變化。由于數(shù)量很多,全部的宏可以在API includes中查看,下面主要列舉一些常用的:

內(nèi)置管線 URP
UNITY_DECLARE_TEX2Dname TEXTURE2DtextureName); SAMPLERsamplerName);
UNITY_DECLARE_TEX2D_NOSAMPLERname TEXTURE2DtextureName);
UNITY_DECLARE_TEX2DARRAYname TEXTURE2D_ARRAYtextureName); SAMPLERsamplerName);
UNITY_SAMPLE_TEX2Dname,uv SAMPLE_TEXTURE2DtextureName,samplerName,coord2
UNITY_SAMPLE_TEX2D_SAMPLERnamesamplername,uv SAMPLE_TEXTURE2DtextureName,samplerNamecoord2
UNITY_SAMPLE_TEX2DARRAYname,uv SAMPLE_TEXTURE2D_ARRAYtextureName,samplerName,coord2,index
UNITY_SAMPLE_TEX2DARRAY_LODname,uv,lod SAMPLE_TEXTURE2D_ARRAY_LODtextureName,samplerName,coord2,indexlod

需要注意SCREENSPACE_TEXTURE變成了TEXTURE2D_X。如果你想要在VR中(Single Pass InstancedMulti-view 模式)制作屏幕效果,你必須使用TEXTURE2D_X定義紋理。這個宏會為你處理正確的紋理聲明(是否為數(shù)組)。對這個紋理采樣的時候必須使用SAMPLE_TEXTURE2D_X,并且對uv使用UnityStereoTransformScreenSpaceTex

Shader輔助函數(shù)

下列函數(shù)可以在此文件中找到:“Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl”.

頂點轉(zhuǎn)換函數(shù)

內(nèi)置管線 URP
float4 UnityObjectToClipPosfloat3 pos float4 TransformObjectToHClipfloat3 positionOS
float3 UnityObjectToViewPosfloat3 pos TransformWorldToViewTransformObjectToWorldpositionOS))

法線轉(zhuǎn)換函數(shù)

內(nèi)置管線 URP
float4 UnityObjectToWorldNormalfloat3 pos float4 TransformObjectToWorldNormalfloat3 normalOS

通用輔助函數(shù)

內(nèi)置管線 URP
float3 UnityWorldSpaceViewDirfloat4 v GetCameraPositionWS() - i.worldPos
float3 UnityObjectToWorldDirfloat4 v TransformObjectToWorldDir(real3 dirOS)
float3 ObjSpaceViewDirfloat4 v 移除了,可以使用TransformWorldToObject(GetCameraPositionWS()) - objectSpacePosition ;
float2 ParallaxOffsethalf h,half height,half3 viewDir 移除了??梢詮腢nityCG.cginc復(fù)制過來
fixed Luminancefixed3 c real Luminancereal3 linearRgb Include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl”
fixed3 DecodeLightmapfixed4 color real3 DecodeLightmap(real4 encodedIlluminance, real4 decodeInstructions) Include “Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl” URP中的decodeInstructionshalf4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0h, 0.0h)
float4 EncodeFloatRGBAfloat v 移除了??梢詮腢nityCG.cginc復(fù)制過來
float DecodeFloatRGBAfloat4 enc 移除了??梢詮腢nityCG.cginc復(fù)制過來
float2 EncodeFloatRGfloat v 移除了。可以從UnityCG.cginc復(fù)制過來
float DecodeFloatRGfloat2 enc 移除了。可以從UnityCG.cginc復(fù)制過來
float2 EncodeViewNormalStereofloat3 n 移除了??梢詮腢nityCG.cginc復(fù)制過來
float3 DecodeViewNormalStereofloat4 enc4 移除了。可以從UnityCG.cginc復(fù)制過來
TANGENT_SPACE_ROTATION

前向渲染輔助函數(shù)

內(nèi)置管線 URP
float3 UnityWorldSpaceLightDir(float4 v) _MainLightPosition.xyz - TransformObjectToWorld(objectSpacePosition) Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl”
float3 ObjSpaceLightDir(float4 v) TransformWorldToObject(_MainLightPosition.xyz)-objectSpacePosition Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl”
float3 Shade4PointLights() 可以使用half3 VertexLighting(float3 positionWS, half3 normalWS) 對于VertexLighting(...) include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”

屏幕空間輔助函數(shù)

內(nèi)置管線 URP
float4 ComputeScreenPos(float4 clipPos) float4 ComputeScreenPosfloat4 positionCS Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl”
float4 ComputeGrabScreenPos(float4 clipPos) 移除了

頂點照明輔助函數(shù)

內(nèi)置管線 URP
float3 ShadeVertexLights (float4 vertex, float3 normal) 移除了,可以嘗試使用UNITY_LIGHTMODEL_AMBIENT.xyz + VertexLighting(...) 對于VertexLighting(...) include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”

可以在“Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl”中找到很多工具函數(shù)。

內(nèi)置著色器變量

除了光照相關(guān)的變量外,其他的變量名都基本沒變

照明

內(nèi)置管線 URP
_LightColor0 _MainLightColor Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl”
_WorldSpaceLightPos0 _MainLightPosition Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl”
_LightMatrix0 移除了。目前尚不支持Cookie
unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0 在URP中,其他光源存儲在數(shù)組/緩沖區(qū)中(取決于平臺)。使用Light GetAdditionalLight(uint i, float3 positionWS)獲取額外光源信息 Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
unity_4LightAtten0 在URP中,其他光源存儲在數(shù)組/緩沖區(qū)中(取決于平臺)。使用Light GetAdditionalLight(uint i, float3 positionWS)獲取額外光源信息 Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
unity_LightColor 在URP中,其他光源存儲在數(shù)組/緩沖區(qū)中(取決于平臺)。使用Light GetAdditionalLight(uint i, float3 positionWS)獲取額外光源信息 Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
unity_WorldToShadow float4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1] 或者_AdditionalLightsWorldToShadow[MAX_VISIBLE_LIGHTS] Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl”

如果要使用循環(huán)所有其他燈光GetAdditionalLight(...),GetAdditionalLightsCount()可以使用來查詢其他燈光計數(shù)。

其他

陰影

有關(guān)陰影的更多信息,“Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl”

內(nèi)置管線 URP
UNITY_SHADOW_COORDSx 移除了。DIY,例如float4 shadowCoord : TEXCOORD0;
TRANSFER_SHADOWa a.shadowCoord = TransformWorldToShadowCoordworldSpacePosition 啟用cascades時,對片段執(zhí)行此操作以避免視覺鬼影
SHADOWS_SCREEN 移除了。不支持。

有關(guān)霧的更多信息,“Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl”.

內(nèi)置管線 URP
UNITY_FOG_COORDS(x) 移除了。DIY,例如float fogCoord : TEXCOORD0;
UNITY_TRANSFER_FOG(o*,outpos) o.fogCoord = ComputeFogFactor(clipSpacePosition.z);
UNITY_APPLY_FOG(coordcol) color = MixFog(color,i.fogCoord);

深度

要使用相機深度紋理,需要include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl” ,然后會自動聲明_CameraDepthTexture,也會包含輔助函數(shù)SampleSceneDepth(...)LoadSceneDepth(...)

內(nèi)置管線 URP
LinearEyeDepthsceneZ LinearEyeDepthsceneZ,_ZBufferParams Include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl”
Linear01DepthsceneZ Linear01DepthsceneZ,_ZBufferParams Include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl”

其他中的其他

內(nèi)置管線 URP
ShadeSH9normal SampleSHnormal Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
unity_ColorSpaceLuminance 移除了。使用Luminance() Include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl”

后處理/視覺特效

URP不支持OnPreCull,OnPreRenderOnPostRenderOnRenderImage這些方法。URP支持OnRenderObjectOnWillRenderObject,但是如果在URP中使用你可能會發(fā)現(xiàn)問題。因此,如果你曾經(jīng)在舊管線創(chuàng)建視覺效果時使用它們,那么現(xiàn)在你需要學(xué)習(xí)新方法了。URP包含以下注入點:

  • 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)
    {
    ...
    }
    ...
}

就像我說的那樣,OnWillRenderObject是受支持的,但是,如果你需要在其中執(zhí)行渲染調(diào)用(例如,水反射/折射),它將無法正常工作。調(diào)用Camera.Render(),你將看到以下消息:

Recursive rendering is not supported in SRP (are you calling Camera.Render from within a render pipeline?)

翻譯過來就是:

SRP不支持遞歸渲染(你是從渲染管道中調(diào)用Camera.Render嗎?)

在這種情況下,URP中應(yīng)該將OnWillRenderObject替換為begin/endCameraRendering(如上面的例子),并調(diào)用RenderSingleCamera(),而不是 Camera.Render()。更改上面的示例,你將獲得以下內(nèi)容

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

使用后處理的另一種方法是使用ScriptableRendererFeature。這篇文章很好地解釋了使用RenderFeature的描邊效果。ScriptableRendererFeature可以讓你將ScriptableRenderPass(es)注入到渲染管線的不同階段,因此是創(chuàng)建后處理效果的強大工具。注入位置可以包含以下:

  • BeforeRendering
  • BeforeRenderingShadows
  • AfterRenderingShadows
  • BeforeRenderingPrepasses
  • AfterRenderingPrePasses
  • BeforeRenderingOpaques
  • AfterRenderingOpaques
  • BeforeRenderingSkybox
  • AfterRenderingSkybox
  • BeforeRenderingTransparents
  • AfterRenderingTransparents
  • BeforeRenderingPostProcessing
  • AfterRenderingPostProcessing
  • AfterRendering

這是ScriptableRendererFeature使用自定義材質(zhì)執(zhí)行blit的簡單示例:

public class CustomRenderPassFeature : ScriptableRendererFeature
{
    class CustomRenderPass : ScriptableRenderPass
    {
        CustomRPSettings _CustomRPSettings;
        RenderTargetHandle _TemporaryColorTexture;

        private RenderTargetIdentifier _Source;
        private RenderTargetHandle _Destination;

        public CustomRenderPass(CustomRPSettings settings)
        {
            _CustomRPSettings = settings;
        }

        public void Setup(RenderTargetIdentifier source, RenderTargetHandle destination)
        {
            _Source = source;
            _Destination = destination;
        }

        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
        {
            _TemporaryColorTexture.Init("_TemporaryColorTexture");
        }

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            CommandBuffer cmd = CommandBufferPool.Get("My Pass");

            if (_Destination == RenderTargetHandle.CameraTarget)
            {
                cmd.GetTemporaryRT(_TemporaryColorTexture.id, renderingData.cameraData.cameraTargetDescriptor, FilterMode.Point);
                cmd.Blit(_Source, _TemporaryColorTexture.Identifier());
                cmd.Blit(_TemporaryColorTexture.Identifier(), _Source, _CustomRPSettings.m_Material);
            }
            else
            {
                cmd.Blit(_Source, _Destination.Identifier(), _CustomRPSettings.m_Material, 0);
            }

            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }

        public override void FrameCleanup(CommandBuffer cmd)
        {
            if (_Destination == RenderTargetHandle.CameraTarget)
            {
                cmd.ReleaseTemporaryRT(_TemporaryColorTexture.id);
            }
        }
    }

    [System.Serializable]
    public class CustomRPSettings
    {
        public Material m_Material;
    }

    public CustomRPSettings m_CustomRPSettings = new CustomRPSettings();
    CustomRenderPass _ScriptablePass;

    public override void Create()
    {
        _ScriptablePass = new CustomRenderPass(m_CustomRPSettings);

        _ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        _ScriptablePass.Setup(renderer.cameraColorTarget, RenderTargetHandle.CameraTarget);
        renderer.EnqueuePass(_ScriptablePass);
    }
}

你可以通過單擊“Create > Rendering > Universal Render Pipeline > Renderer Feature”來創(chuàng)建一個ScriptableRendererFeature。你創(chuàng)建的功能必須添加到你的中ForwardRenderer。為此,選擇ForwardRenderer,單擊Add Renderer Feature,然后選擇要添加的功能。你可以在Inspector中公開屬性,例如上面的例子中包含了一個材質(zhì)球?qū)傩浴?/p>

結(jié)語

由于Unity和URP、SRP都在快速迭代更新,本文也會不定時更新。如果有問題,你可以在本文原文中評論,也可以通過微信:zhz11235或者QQ:329541945找到我。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容