本文转载自: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 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

"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

其他有用的包括:

灯光模式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中的decodeInstructions是half4(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不支持OnPreCull,OnPreRender,OnPostRender和OnRenderImage这些方法。URP支持OnRenderObject和OnWillRenderObject,但是如果在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的简单示例:

publicclass 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

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐