美文网首页unity
内置管线Shader升级到URP详细手册

内置管线Shader升级到URP详细手册

作者: 洪智 | 来源:发表于2021-03-03 21:28 被阅读0次

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

    本文初版内容翻译自:https://teodutra.com/unity/shaders/urp/graphics/2020/05/18/From-Built-in-to-URP/

    译者:大智
    后续补充:大智

    内置管线Shader升级到URP详细手册

    总体结构

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

    内置管线 URP
    CGPROGRAM HLSLPROGRAM HLSL程序
    ENDCG ENDHLSL ENDHLSL
    CGINCLUDE HLSLINCLUDE HLSLINCLUDE

    Include文件

    内容 内置管线 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内没有,可以参考项目:在此处

    其他有用的包括:

    灯光模式LightMode

    内置管线 URP
    ForwardBase UniversalForward
    ForwardAdd 移除
    Deferred以及相关 尚未支持
    Vertex及相关 移除
    ShadowCaster ShadowCaster
    MotionVectors 尚未支持

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

    • DepthOnly
    • Meta (for lightmap baking)
    • Universal2D

    变体Variants

    URP支持某些变体,因此,根据你使用的功能,可能需要使用#pragma multi_compile添加一些关键字:

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

    预定义的着色器宏

    辅助宏

    内置管线 URP
    UNITY_PROJ_COORD(a) 移除了,使用a.xy / a.w代替
    UNITY_INITIALIZE_OUTPUT(typename) ZERO_INITIALIZE(typename)

    阴影贴图

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

    内置管线 URP
    UNITY_DECLARE_SHADOWMAPtex TEXTURE2D_SHADOW_PARAMtextureNamesamplerName
    UNITY_SAMPLE_SHADOWtexuv SAMPLE_TEXTURE2D_SHADOWtextureNamesamplerNamecoord3
    UNITY_SAMPLE_SHADOW_PROJtexuv SAMPLE_TEXTURE2D_SHADOWtextureNamesamplerNamecoord4.xyz/coord4.w

    纹理/采样器声明宏

    Unity有很多纹理/采样器宏来改善API之间的交叉兼容性,但是人们并不习惯使用它们。URP中这些宏的名称有所变化。由于数量很多,全部的宏可以在API includes中查看,下面主要列举一些常用的:

    内置管线 URP
    UNITY_DECLARE_TEX2Dname TEXTURE2DtextureName); SAMPLERsamplerName);
    UNITY_DECLARE_TEX2D_NOSAMPLERname TEXTURE2DtextureName);
    UNITY_DECLARE_TEX2DARRAYname TEXTURE2D_ARRAYtextureName); SAMPLERsamplerName);
    UNITY_SAMPLE_TEX2Dnameuv SAMPLE_TEXTURE2DtextureNamesamplerNamecoord2
    UNITY_SAMPLE_TEX2D_SAMPLERnamesamplernameuv SAMPLE_TEXTURE2DtextureNamesamplerNamecoord2
    UNITY_SAMPLE_TEX2DARRAYnameuv SAMPLE_TEXTURE2D_ARRAYtextureNamesamplerNamecoord2index
    UNITY_SAMPLE_TEX2DARRAY_LODnameuvlod SAMPLE_TEXTURE2D_ARRAY_LODtextureNamesamplerNamecoord2indexlod

    需要注意SCREENSPACE_TEXTURE变成了TEXTURE2D_X。如果你想要在VR中(Single Pass InstancedMulti-view 模式)制作屏幕效果,你必须使用TEXTURE2D_X定义纹理。这个宏会为你处理正确的纹理声明(是否为数组)。对这个纹理采样的时候必须使用SAMPLE_TEXTURE2D_X,并且对uv使用UnityStereoTransformScreenSpaceTex

    Shader辅助函数

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

    顶点转换函数

    内置管线 URP
    float4 UnityObjectToClipPosfloat3 pos float4 TransformObjectToHClipfloat3 positionOS
    float3 UnityObjectToViewPosfloat3 pos TransformWorldToViewTransformObjectToWorldpositionOS))

    法线转换函数

    内置管线 URP
    float4 UnityObjectToWorldNormalfloat3 pos float4 TransformObjectToWorldNormalfloat3 normalOS

    通用辅助函数

    内置管线 URP
    float3 UnityWorldSpaceViewDirfloat4 v GetCameraPositionWS() - i.worldPos
    float3 UnityObjectToWorldDirfloat4 v TransformObjectToWorldDir(real3 dirOS)
    float3 ObjSpaceViewDirfloat4 v 移除了,可以使用TransformWorldToObject(GetCameraPositionWS()) - objectSpacePosition ;
    float2 ParallaxOffsethalf hhalf heighthalf3 viewDir 移除了。可以从UnityCG.cginc复制过来
    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 移除了。可以从UnityCG.cginc复制过来
    float DecodeFloatRGBAfloat4 enc 移除了。可以从UnityCG.cginc复制过来
    float2 EncodeFloatRGfloat v 移除了。可以从UnityCG.cginc复制过来
    float DecodeFloatRGfloat2 enc 移除了。可以从UnityCG.cginc复制过来
    float2 EncodeViewNormalStereofloat3 n 移除了。可以从UnityCG.cginc复制过来
    float3 DecodeViewNormalStereofloat4 enc4 移除了。可以从UnityCG.cginc复制过来
    TANGENT_SPACE_ROTATION

    前向渲染辅助函数

    内置管线 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”

    屏幕空间辅助函数

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

    顶点照明辅助函数

    内置管线 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”中找到很多工具函数。

    内置着色器变量

    除了光照相关的变量外,其他的变量名都基本没变

    照明

    内置管线 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_4LightPosX0unity_4LightPosY0unity_4LightPosZ0 在URP中,其他光源存储在数组/缓冲区中(取决于平台)。使用Light GetAdditionalLight(uint i, float3 positionWS)获取额外光源信息 Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
    unity_4LightAtten0 在URP中,其他光源存储在数组/缓冲区中(取决于平台)。使用Light GetAdditionalLight(uint i, float3 positionWS)获取额外光源信息 Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
    unity_LightColor 在URP中,其他光源存储在数组/缓冲区中(取决于平台)。使用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”

    如果要使用循环所有其他灯光GetAdditionalLight(...)GetAdditionalLightsCount()可以使用来查询其他灯光计数。

    其他

    阴影

    有关阴影的更多信息,“Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl”

    内置管线 URP
    UNITY_SHADOW_COORDSx 移除了。DIY,例如float4 shadowCoord : TEXCOORD0;
    TRANSFER_SHADOWa a.shadowCoord = TransformWorldToShadowCoordworldSpacePosition 启用cascades时,对片段执行此操作以避免视觉鬼影
    SHADOWS_SCREEN 移除了。不支持。

    有关雾的更多信息,“Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl”.

    内置管线 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(colori.fogCoord);

    深度

    要使用相机深度纹理,需要include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl” ,然后会自动声明_CameraDepthTexture,也会包含辅助函数SampleSceneDepth(...)LoadSceneDepth(...)

    内置管线 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”

    其他中的其他

    内置管线 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不支持OnPreCullOnPreRenderOnPostRenderOnRenderImage这些方法。URP支持OnRenderObjectOnWillRenderObject,但是如果在URP中使用你可能会发现问题。因此,如果你曾经在旧管线创建视觉效果时使用它们,那么现在你需要学习新方法了。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是受支持的,但是,如果你需要在其中执行渲染调用(例如,水反射/折射),它将无法正常工作。调用Camera.Render(),你将看到以下消息:

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

    翻译过来就是:

    SRP不支持递归渲染(你是从渲染管道中调用Camera.Render吗?)

    在这种情况下,URP中应该将OnWillRenderObject替换为begin/endCameraRendering(如上面的例子),并调用RenderSingleCamera(),而不是 Camera.Render()。更改上面的示例,你将获得以下内容

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

    使用后处理的另一种方法是使用ScriptableRendererFeature这篇文章很好地解释了使用RenderFeature的描边效果。ScriptableRendererFeature可以让你将ScriptableRenderPass(es)注入到渲染管线的不同阶段,因此是创建后处理效果的强大工具。注入位置可以包含以下:

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

    这是ScriptableRendererFeature使用自定义材质执行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”来创建一个ScriptableRendererFeature。你创建的功能必须添加到你的中ForwardRenderer。为此,选择ForwardRenderer,单击Add Renderer Feature,然后选择要添加的功能。你可以在Inspector中公开属性,例如上面的例子中包含了一个材质球属性。

    结语

    由于Unity和URP、SRP都在快速迭代更新,本文也会不定时更新。如果有问题,你可以在本文原文中评论,也可以通过微信:zhz11235或者QQ:329541945找到我。

    相关文章

      网友评论

        本文标题:内置管线Shader升级到URP详细手册

        本文链接:https://www.haomeiwen.com/subject/dowmiktx.html