Unity Built-in Shader转URP Shader 接口查询对照表

本篇文章转自Teofilo Dutra编写的《From Built-in to URP》,其中有很多在写URP管线Shader时需要用到的函数,作为备忘速查表非常实用,所以记录于此。本文经过精简和翻译,不一定适用于大家,可以点击上方链接跳转至作者原文。本文是基于7.3版本的URP编写的,有些暂时还不支持的内容可能在后续版本更新迭代。

结构

首先要在SubShader的Tags中添加”RenderPipeline” = “UniversalPipeline”,并且使用HLSL的宏代替旧版的CG语言宏。

Built-inURP
CGPROGRAM / HLSLPROGRAMHLSLPROGRAM
ENDCG / ENDHLSLENDHLSL
CGINCLUDE / HLSLINCLUDEHLSLINCLUDE

Include文件的改动

ContentBuilt-inURP
CoreUnity.cgincPackages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl
LightAutoLight.cgincPackages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl
ShadowsAutoLight.cgincPackages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl
Surface shadersLighting.cginc

其他常用的include文件:

  • Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl
  • Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl
  • Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl
  • Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl
  • Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl
  • Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl
  • Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTextue.hlsl

光照模式

Built-inURP
ForwardBaseUniversalForward
ForwardAdd
Deferred and relatedUniversalGBuffer seems to have just been added to URP
Vertex and related
ShadowCasterShadowCaster
MotionVectors暂不支持

URP其他支持的光照模式:

  • DepthOnly
  • Meta (用于烘焙光照贴图)
  • 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

预定义的着色器预处理宏

辅助宏(Helpers)

Built-inURP
UNITY_PROJ_COORD(a)无,使用 a.xy/a.w 来代替
UNITY_INITIALIZE_OUTPUT(type, name)ZERO_INITIALIZE(type, name)

阴影贴图

需要包含 Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl

Built-inURP
UNITY_DECLARE_SHADOWMAP(tex)TEXTURE2D_SHADOW_PARAM(textureName, samplerName)
UNITY_SAMPLE_SHADOW(tex, uv)SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3)
UNITY_SAMPLE_SHADOW_PROJ(tex, uv)SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord4.xyz/coord4.w)

纹理/采样器的声明宏

Built-inURP
UNITY_DECLARE_TEX2D(name)TEXTURE2D(textureName); SAMPLER(samplerName);
UNITY_DECLARE_TEX2D_NOSAMPLER(name)TEXTURE2D(textureName);
UNITY_DECLARE_TEX2DARRAY(name)TEXTURE2D_ARRAY(textureName); SAMPLER(samplerName);
UNITY_SAMPLE_TEX2D(name, uv)SAMPLE_TEXTURE2D(textureName, samplerName, coord2)
UNITY_SAMPLE_TEX2D_SAMPLER(name, samplername, uv)SAMPLE_TEXTURE2D(textureName, samplerName, coord2)
UNITY_SAMPLE_TEX2DARRAY(name, uv)SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index)
UNITY_SAMPLE_TEX2DARRAY_LOD(name, uv, lod)SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod)

内置的着色器辅助函数

可以在 Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl 看到下方的所有函数

顶点变换函数

Built-inURP
float4 UnityObjectToClipPos(float3 pos)float4 TransformObjectToHClip(float3 positionOS)
float3 UnityObjectToViewPos(float3 pos)TransformWorldToView(TransformObjectToWorld(positionOS))

泛用的辅助函数

Built-inURPInclude
float3 WorldSpaceViewDir (float4 v)float3 GetWorldSpaceViewDir(float3 positionWS)Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl”
float3 ObjSpaceViewDir (float4 v)无,使用 TransformWorldToObject(GetCameraPositionWS()) - objectSpacePosition;
float2 ParallaxOffset (half h, half height, half3 viewDir)可能没有,从 UnityCG.cginc 复制
fixed Luminance (fixed3 c)real Luminance(real3 linearRgb)Include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl”
fixed3 DecodeLightmap (fixed4 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 EncodeFloatRGBA (float v)可能没有, 从 UnityCG.cginc 复制
float DecodeFloatRGBA (float4 enc)可能没有, 从 UnityCG.cginc 复制
float2 EncodeFloatRG (float v)可能没有, 从 UnityCG.cginc 复制
float DecodeFloatRG (float2 enc)可能没有, 从 UnityCG.cginc 复制
float2 EncodeViewNormalStereo (float3 n)可能没有, 从 UnityCG.cginc 复制
float3 DecodeViewNormalStereo (float4 enc4)可能没有, 从 UnityCG.cginc 复制

前向渲染辅助函数

Built-inURPInclude
float3 WorldSpaceLightDir (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)include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”

屏幕空间辅助函数

Built-inURPInclude
float4 ComputeScreenPos (float4 clipPos)float4 ComputeScreenPos(float4 positionCS)Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl”
float4 ComputeGrabScreenPos (float4 clipPos)

顶点光照的辅助函数

Built-inURPInclude
float3 ShadeVertexLights (float4 vertex, float3 normal)无,可尝试用 UNITY_LIGHTMODEL_AMBIENT.xyz + VertexLighting(…)include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”

可以在 Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl 中找到一些通用函数

内置的着色器变量

Built-inURPInclude
_LightColor0_MainLightColorInclude “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl”
_WorldSpaceLightPos0_MainLightPositionInclude “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl”
_LightMatrix0可能还不支持
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0URP中,额外的灯光存储在一个数组或缓冲中(取决于平台),使用Light GetAdditionalLight(uint i, float3 positionWS)获取光照信息Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
unity_4LightAtten0URP中,额外的灯光存储在一个数组或缓冲中(取决于平台),使用Light GetAdditionalLight(uint i, float3 positionWS)获取光照信息Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
unity_LightColorURP中,额外的灯光存储在一个数组或缓冲中(取决于平台),使用Light GetAdditionalLight(uint i, float3 positionWS)获取光照信息Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
unity_WorldToShadowfloat4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1] or _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

Built-inURP
UNITY_SHADOW_COORDS(x)可能没有,可以写作float4 shadowCoord : TEXCOORD0;
TRANSFER_SHADOW(a)a.shadowCoord = TransformWorldToShadowCoord(worldSpacePosition)
SHADOWS_SCREEN暂不支持

更多雾相关的函数可以查看 Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl

Built-inURP
UNITY_FOG_COORDS(x)可能没有,可以写作float fogCoord : TEXCOORD0;
UNITY_TRANSFER_FOG(o, outpos)o.fogCoord = ComputeFogFactor(clipSpacePosition.z);
UNITY_APPLY_FOG(coord, col)color = MixFog(color, i.fogCoord);

深度

可以包含 “Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl” 并使用 _CameraDepthTexture来调用深度纹理。也可以使用SampleSceneDepth(…) 和 LoadSceneDepth(…)。

Built-inURPInclude
LinearEyeDepth(sceneZ)LinearEyeDepth(sceneZ, _ZBufferParams)Include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl”
Linear01Depth(sceneZ)Linear01Depth(sceneZ, _ZBufferParams)Include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl”

其他

Built-inURPInclude
ShadeSH9(normal)SampleSH(normal)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. 支持 OnRenderObject 和 OnWillRenderObject。RenderPipelineManager提供了渲染管线中注入的位置:

  • beginCameraRendering(ScriptableRenderContext context, Camera camera)
  • endCameraRendering(ScriptableRenderContext context, Camera camera)
  • beginFrameRendering(ScriptableRenderContext context,Camera[] cameras)
  • endFrameRendering(ScriptableRenderContext context,Camera[] cameras)

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void OnEnable()
{
	RenderPipelineManager.beginCameraRendering += MyCameraRendering;
}

void OnDisable()
{
	RenderPipelineManager.beginCameraRendering -= MyCameraRendering;
}

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


另外,可以创建ScriptableRendererFeature来实现后期处理效果。可以在管线的不同阶段注入ScriptableRenderPasses:

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

下面是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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);
    }
}
  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基本的Unity URP次表面散射(SSS)着色器示例: ``` Shader "Custom/URP SSS" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} _NormalMap ("Normal Map", 2D) = "bump" {} _SubsurfaceColor ("Subsurface Color", Color) = (1,1,1,1) _SubsurfaceRadius ("Subsurface Radius", Range(0.0,1.0)) = 0.25 _ThicknessMap ("Thickness Map", 2D) = "white" {} _SpecularColor ("Specular Color", Color) = (0.5,0.5,0.5,1) _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 } SubShader { Tags {"RenderType"="Opaque"} LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; float4 tangent : TANGENT; }; struct v2f { float2 uv : TEXCOORD0; float3 worldPos : TEXCOORD1; float3 worldNormal : TEXCOORD2; float3 worldTangent : TEXCOORD3; float3 worldBitangent : TEXCOORD4; UNITY_VERTEX_INPUT_INSTANCE_ID }; sampler2D _MainTex; sampler2D _NormalMap; sampler2D _ThicknessMap; float4 _MainTex_ST; float4 _ThicknessMap_ST; float _SubsurfaceRadius; float4 _SubsurfaceColor; float4 _SpecularColor; float _Glossiness; float _Metallic; float3 CalculateTangent(float3 n, float3 p, float2 uv, float3 dpdu) { float3 dpdv = cross(n, dpdu); float3 t = normalize(dpdv - uv.y * dpdu); return t; } float3 CalculateBitangent(float3 n, float3 p, float2 uv, float3 dpdu) { float3 dpdv = cross(n, dpdu); float3 b = normalize(cross(n, dpdv)); return b; } float3 CalculateSubsurface(float3 worldPos, float3 worldNormal, float3 worldTangent, float3 worldBitangent) { // Calculate tangent space vectors float3x3 TBN = float3x3(worldTangent, worldBitangent, worldNormal); // Calculate thickness float thickness = tex2D(_ThicknessMap, TRANSFORM_TEX(worldPos, _ThicknessMap)).r; // Calculate subsurface scattering float3 subsurface = _SubsurfaceColor.rgb * thickness * _SubsurfaceRadius; // Transform subsurface scattering to world space subsurface = mul(TBN, subsurface); return subsurface; } float4 LightingURP(SurfaceOutputStandard s, float3 lightDir, float3 worldPos, float atten) { // Calculate subsurface scattering float3 subsurface = CalculateSubsurface(worldPos, s.Normal, s.Tangent, s.Bitangent); // Calculate diffuse lighting float diff = max(0.0, dot(s.Normal, lightDir)); float3 diffuse = (s.Albedo * _LightColor0.rgb * diff); // Calculate specular lighting float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos)); float3 halfDir = normalize(lightDir + viewDir); float spec = pow(max(0.0, dot(s.Normal, halfDir)), s.Smoothness); float3 specular = _SpecularColor.rgb * _LightColor0.rgb * spec; // Combine lighting float3 finalColor = ((diffuse + specular) * atten) + subsurface; return float4(finalColor, s.Alpha); } v2f vert (appdata v) { v2f o; o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; o.worldNormal = UnityObjectToWorldNormal(v.normal); o.worldTangent = UnityObjectToWorldDir(UnityObjectToWorldDir(v.tangent.xyz, UNITY_MATRIX_IT_MV), UNITY_MATRIX_IT_MV); o.worldBitangent = cross(o.worldNormal, o.worldTangent) * v.tangent.w; o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_SETUP_INSTANCE_ID(v); return o; } fixed4 frag (v2f i) : SV_Target { SurfaceOutputStandard s = SurfaceOutputStandard(); s.Albedo = tex2D(_MainTex, i.uv).rgb; s.Normal = UnpackNormal(tex2D(_NormalMap, i.uv)); s.Smoothness = _Glossiness; s.Metallic = _Metallic; float3 worldPos = i.worldPos; float3 worldNormal = normalize(i.worldNormal); float3 worldTangent = normalize(i.worldTangent); float3 worldBitangent = normalize(i.worldBitangent); float4 finalColor = LightingURP(s, normalize(_WorldSpaceLightPos0.xyz), worldPos, _LightColor0.a); return finalColor; } ENDCG } } FallBack "Diffuse" } ``` 这个着色器包含了一个基本的表面纹理、法线贴图、次表面散射颜色和半径、厚度贴图、高光颜色、光滑度和金属度选项。在顶点着色器中,我们还计算了Tangent和Bitangent向量,并传递给片段着色器以计算次表面散射。在片段着色器中,我们计算了次表面散射、漫反射和高光光照,并将它们合并以产生最终颜色。请注意,此着色器是基于URP版本的标准表面着色器,并使用UnityCG.cginc文件中定义的LightingURP函数来计算光照。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值