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

本文转载自:https://www.jianshu.com/p/3fef69e2efb6

作为技术资料记录和备份,避免遗忘或删除

//================以下为具体内容==========================

本文基于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 HLSLPROGRAMHLSL程序
ENDCG ENDHLSLENDHLSL
CGINCLUDE HLSLINCLUDEHLSLINCLUDE

Include文件

内容内置管线URP
CoreUnityCG.cgincPackages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl
LightAutoLight.cgincPackages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl
ShadowAutoLight.cgincPackages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl
表面着色器Lighting.cgincURP内没有,可以参考项目:在此处

其他有用的包括:

灯光模式LightMode

内置管线URP
ForwardBaseUniversalForward
ForwardAdd移除
Deferred以及相关尚未支持
Vertex及相关移除
ShadowCasterShadowCaster
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_SHADOWMAPtexTEXTURE2D_SHADOW_PARAMtextureNamesamplerName
UNITY_SAMPLE_SHADOWtexuvSAMPLE_TEXTURE2D_SHADOWtextureNamesamplerNamecoord3
UNITY_SAMPLE_SHADOW_PROJtexuvSAMPLE_TEXTURE2D_SHADOWtextureNamesamplerNamecoord4.xyz/coord4.w

纹理/采样器声明宏

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

内置管线URP
UNITY_DECLARE_TEX2DnameTEXTURE2DtextureName); SAMPLERsamplerName);
UNITY_DECLARE_TEX2D_NOSAMPLERnameTEXTURE2DtextureName);
UNITY_DECLARE_TEX2DARRAYnameTEXTURE2D_ARRAYtextureName); SAMPLERsamplerName);
UNITY_SAMPLE_TEX2DnameuvSAMPLE_TEXTURE2DtextureNamesamplerNamecoord2
UNITY_SAMPLE_TEX2D_SAMPLERnamesamplernameuvSAMPLE_TEXTURE2DtextureNamesamplerNamecoord2
UNITY_SAMPLE_TEX2DARRAYnameuvSAMPLE_TEXTURE2D_ARRAYtextureNamesamplerNamecoord2index
UNITY_SAMPLE_TEX2DARRAY_LODnameuvlodSAMPLE_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 posfloat4 TransformObjectToHClipfloat3 positionOS
float3 UnityObjectToViewPosfloat3 posTransformWorldToViewTransformObjectToWorldpositionOS))

法线转换函数

内置管线URP
float4 UnityObjectToWorldNormalfloat3 posfloat4 TransformObjectToWorldNormalfloat3 normalOS

通用辅助函数

内置管线URP
float3 UnityWorldSpaceViewDirfloat4 vGetCameraPositionWS() - i.worldPos
float3 UnityObjectToWorldDirfloat4 vTransformObjectToWorldDir(real3 dirOS)
float3 ObjSpaceViewDirfloat4 v移除了,可以使用TransformWorldToObject(GetCameraPositionWS()) - objectSpacePosition ;
float2 ParallaxOffsethalf hhalf heighthalf3 viewDir移除了。可以从UnityCG.cginc复制过来
fixed Luminancefixed3 creal Luminancereal3 linearRgbInclude “Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl”
fixed3 DecodeLightmapfixed4 colorreal3 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)-objectSpacePositionInclude “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 positionCSInclude “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_MainLightColorInclude “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl”
_WorldSpaceLightPos0_MainLightPositionInclude “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_WorldToShadowfloat4x4 _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_SHADOWaa.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
LinearEyeDepthsceneZLinearEyeDepthsceneZ_ZBufferParamsInclude “Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl”
Linear01DepthsceneZLinear01DepthsceneZ_ZBufferParamsInclude “Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl”

其他中的其他

内置管线URP
ShadeSH9normalSampleSHnormalInclude “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中公开属性,例如上面的例子中包含了一个材质球属性。

结语



作者:洪智
链接:https://www.jianshu.com/p/3fef69e2efb6
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值