|
一、前言
URP正式发布已经很久了,现在是2023年,但是发现现在网上的一些Shader教程还是大多都是基于Built-in的,感觉对于新手同学们不是很友好,关于URP的教程又少之又少。
这里结合个人经验以及网络上的一些资料,介绍一下如何从Built-in升级到URP。

<hr/>二、项目设置升级URP
1、从Package Manager下载Universal RP
在导航栏中Window->Package Manager,搜索Universal RP

2、将项目设置中的管线配置为URP
首先需要生成URP相关Asset资产
在导航栏中Assets ->Create -> Rendering - >Universal Render Pipeline -> Pipeline Asset创建


创建完后默认名称
然后在导航栏的Edit中打开Project Setting面板

选择Graphics,然后再其中的Scriptable Render Pipeline settings中选择UniversalRenderPipelineAsset

注意如果项目做不同的品质设置,到Quality里每一栏都指定对应的UniversalRenderPipelineAsset

最好做项目的时候都设置一下,有时候这里没设置可能有坑
3.将系统默认的材质升级到URP
操作完第二步后,发现场景里的颜色变成了粉色,此时不要慌
- 如果是Built-In的默认标准材质,那么可以通过URP提供的工具改回来
- 如果是自己编写的Shader需要重新编写一下代码(后面会从Shader代码的角度讲解怎么升级)

在导航栏中Edit -> Render Pipeline -> Universal Render Pipeline -> Upgrade Project Material to UniversalRP Materials


主要的操作就是将原来旧材质球里用到了的默认shader替换为urp里对应的shader

如果用的不是系统自带的Shader那么将不能转换

转换失败的例子
至此Unity设置方面已经完成
<hr/>三、Shader代码升级
强烈建议用Jetbrains Rider做开发工具,Shader代码高亮和补全用得很舒服
参靠来源:
URP管线比较大的变化就是,不再支持多个渲染Pass
在Built-in里面,前向渲染的方式为:
- ForwardBase Pass计算主光
- ForwardAdd Pass计算其他光照
光源越多调用的Pass数量就越多
在URP里面,采用的是在一个Pass中遍历所有光源进行计算
1.Unlit Shader举例
我们这里先拿一个最简单的Unlit Shader进行举例说明
Built-in:
Shader &#34;Unlit/test_CG&#34;
{
Properties
{
_MainTex (&#34;Texture&#34;, 2D) = &#34;white&#34; {}
_Color(&#34;Base Color&#34;,Color)=(1,1,1,1)
}
SubShader
{
Tags { &#34;RenderType&#34;=&#34;Opaque&#34; }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include &#34;UnityCG.cginc&#34;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
return col * _Color;
}
ENDCG
}
}
}
URP(HLSL) :
Shader &#34;Unlit/test_URP&#34;
{
Properties
{
_MainTex (&#34;Texture&#34;, 2D) = &#34;white&#34; {}
_Color(&#34;Base Color&#34;,Color)=(1,1,1,1)
}
SubShader
{
Tags {
&#34;RenderPipeline&#34;=&#34;UniversalPipeline&#34;//声明这是一个URP Shader!
&#34;Queue&#34;=&#34;Geometry&#34;
&#34;RenderType&#34;=&#34;Opaque&#34; }
LOD 100
HLSLINCLUDE //在Pass外部,引入文件或者定义,均在HLSLINCLUDE 完成
//用于替换 CG中核心代码库 #include &#34;UnityCG.cginc&#34;
#include &#34;Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl&#34;//函数库:主要用于各种的空间变换
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); //采样贴图,采样前面汇入的maintex贴图,贴图采样器,以及贴图st
//除了贴图外,在片元Shader中使用到的暴露在Inspector面板上的变量,都需要缓存到CBUFFER中,用于 SRP Batcher
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float4 _Color;
CBUFFER_END
ENDHLSL
Pass
{
// CGPROGRAM
HLSLPROGRAM //替换掉 CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// #include &#34;UnityCG.cginc&#34;
// Pass 外已经引入了 Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
// o.vertex = UnityObjectToClipPos(v.vertex);
o.vertex = TransformObjectToHClip(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
//fixed4 不再URP中支持,需要用half4 或者 float4
float4 frag (v2f i) : SV_Target
{
// sample the texture
// fixed4 col = tex2D(_MainTex, i.uv);
//HLSL 里贴图采样函数需要替换
float4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv);
return col * _Color;
}
// ENDCG
ENDHLSL
}
}
}
我在代码里做了一些注释,可以看到转换时都有哪些修改项,基本对照着类似的进行改动即可完成Shader的升级
这只是个简单的例子,后面我们详细的来对照讲解。
2.Built-in到URP函数对照整理
整体结构:
- 需要在Tag里添加&#34;RenderPipeline&#34; = &#34;UniversalPipeline&#34;
- 所有的URP Shader代码均包含在HLSLPROGRAM/ENDHLSL 内
Built-in | URP | CGPROGRAM
HLSLPROGRAM | HLSLPROGRAM | ENDCG
ENDHLSL | ENDHLSL | CGINCLUDE
HLSLINCLUDE | HLSLINCLUDE | Include文件:
Content | Built-in | URP | Core | Unity.cginc | Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl | Light | AutoLight.cginc | Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl | Shadows | AutoLight.cginc | Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl | Surface shaders | Lighting.cginc | URP内不支持 | 所有的HLSL代码均在Packages/Universal RP内,可以翻看详细源码

Light Modes(照明模式)
Built-in | URP | ForwardBase | UniversalForward | ForwardAdd | 移除 | Deferred and related | 尚未支持 | Vertex and related | 移除 | ShadowCaster | ShadowCaster | MotionVectors | 尚未支持 | 还有一些其他的Light Modes:
- 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
预定义的着色器宏
Built-in | URP | UNITY_PROJ_COORD(a) | 使用a.xy / a.w代替 | UNITY_INITIALIZE_OUTPUT(type, name) | ZERO_INITIALIZE(type,name) |
Shadow Mapping(阴影贴图)
#include &#34;Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl&#34;
Built-in | URP | 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) |
Texture/Sampler Declaration Macros(纹理贴图采样)
这里仅列举一些常用的,更多的可以查看API includes
Built-in | URP | 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) |
Shader辅助函数
代码文件可以查看:
顶点转换函数
Built-in | URP | float4 UnityObjectToClipPos(float3 pos) | float4 TransformObjectToHClip(float3 positionOS) | float3 UnityObjectToViewPos(float3 pos) | TransformWorldToView(TransformObjectToWorld(positionOS)) | 法线转换函数
Built-in | URP | float4 UnityObjectToWorldNormal(float3 pos) | float4 TransformObjectToWorldNormal(float3 normalOS) | 通用辅助函数
Built-in | URP | float3 WorldSpaceViewDir (float4 v) | float3 GetWorldSpaceViewDir(float3 positionWS) | Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl” | float3 UnityObjectToWorldDir(float4 v) | TransformObjectToWorldDir(real3 dirOS) | 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-in | URP | 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) - 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” | 屏幕空间辅助函数
Built-in | URP | float4 ComputeScreenPos (float4 clipPos) | float4 ComputeScreenPos(float4 positionCS) | Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl” | float4 ComputeGrabScreenPos (float4 clipPos) | 移除了 | 顶点照明辅助函数
Built-in | URP | loat3 ShadeVertexLights (float4 vertex, float3 normal) | 移除了,可以尝试使用UNITY_LIGHTMODEL_AMBIENT.xyz + VertexLighting(...) | 对于VertexLighting(...) include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl” | 内置着色器变量
除了光照相关的变量外,其他的变量名都基本没变
Lighting(照明)
Built-in | 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中,其他光源存储在数组/缓冲区中(取决于平台)。使用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()可以使用来查询其他灯光计数。
其他
Shadows(阴影)
Built-in | URP | UNITY_SHADOW_COORDS(x) | 移除了。DIY,例如float4 shadowCoord : TEXCOORD0; | TRANSFER_SHADOW(a) | a.shadowCoord = TransformWorldToShadowCoord(worldSpacePosition) | SHADOWS_SCREEN | 移除了 | Fog(雾)
Built-in | URP | UNITY_FOG_COORDS(x) | 移除了。DIY,例如float fogCoord : TEXCOORD0; | UNITY_TRANSFER_FOG(o*,outpos) | o.fogCoord = ComputeFogFactor(clipSpacePosition.z); | UNITY_APPLY_FOG(coord,col) | color = MixFog(color,i.fogCoord); | Depth(深度)
要使用相机深度纹理,需要include &#34;Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl&#34; ,然后会自动声明_CameraDepthTexture,也会包含辅助函数SampleSceneDepth(...)和LoadSceneDepth(...)
Built-in | URP | 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-in | URP | 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” | 基本上Shader代码对照上述整理的内容,做完更替后即可完成升级。
四、尾语
另外关于SRP Batcher-URP的优化实践,可以参考我之前写的文章
关于Unity不同的渲染管线的区别,可以参考这个回答:
以上内容部分部分来自自我实践,部分来自网络整理。
如果看完对你有帮助的话,麻烦点个赞或者点个关注嘞! |
|