本文基于Unity2020.2稳摄,URP10赦役,更新于20210303
本文初版內(nèi)容翻譯自:https://teodutra.com/unity/shaders/urp/graphics/2020/05/18/From-Built-in-to-URP/
譯者:大智
后續(xù)補(bǔ)充:大智
內(nèi)置管線Shader升級到URP詳細(xì)手冊
總體結(jié)構(gòu)
1、在SubShader的Tags中添加"RenderPipeline" = "UniversalPipeline"
2、所有URP著色器都是HLSL編寫的,使用宏HLSL
包含的shader代碼
3、使用HLSLINCLUDE替代CGINCLUDE
內(nèi)置管線 | URP |
---|---|
CGPROGRAM HLSLPROGRAM | HLSL程序 |
ENDCG ENDHLSL | ENDHLSL |
CGINCLUDE HLSLINCLUDE | HLSLINCLUDE |
Include文件
內(nèi)容 | 內(nèi)置管線 | 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內(nèi)沒有翘鸭,可以參考項目:在此處 |
其他有用的包括:
- 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
燈光模式LightMode
內(nèi)置管線 | URP |
---|---|
ForwardBase | UniversalForward |
ForwardAdd | 移除 |
Deferred以及相關(guān) | 尚未支持 |
Vertex及相關(guān) | 移除 |
ShadowCaster | ShadowCaster |
MotionVectors | 尚未支持 |
支持的其他照明模式包括:
- DepthOnly
- Meta (for lightmap baking)
- Universal2D
變體Variants
URP支持某些變體,因此戳葵,根據(jù)你使用的功能就乓,可能需要使用#pragma multi_compile
添加一些關(guān)鍵字:
_MAIN_LIGHT_SHADOWS
_MAIN_LIGHT_SHADOWS_CASCADE
_ADDITIONAL_LIGHTS_VERTEX
_ADDITIONAL_LIGHTS
_ADDITIONAL_LIGHT_SHADOWS
_SHADOWS_SOFT
_MIXED_LIGHTING_SUBTRACTIVE
預(yù)定義的著色器宏
輔助宏
內(nèi)置管線 | URP |
---|---|
UNITY_PROJ_COORD(a) | 移除了,使用a.xy / a.w代替 |
UNITY_INITIALIZE_OUTPUT(type拱烁,name) | ZERO_INITIALIZE(type生蚁,name) |
陰影貼圖
必須include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl”
內(nèi)置管線 | 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) |
紋理/采樣器聲明宏
Unity有很多紋理/采樣器宏來改善API之間的交叉兼容性猛们,但是人們并不習(xí)慣使用它們念脯。URP中這些宏的名稱有所變化。由于數(shù)量很多弯淘,全部的宏可以在API includes中查看绿店,下面主要列舉一些常用的:
內(nèi)置管線 | 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) |
需要注意SCREENSPACE_TEXTURE
變成了TEXTURE2D_X
驶社。如果你想要在VR中(Single Pass Instanced 或 Multi-view 模式)制作屏幕效果企量,你必須使用TEXTURE2D_X
定義紋理。這個宏會為你處理正確的紋理聲明(是否為數(shù)組)亡电。對這個紋理采樣的時候必須使用SAMPLE_TEXTURE2D_X
届巩,并且對uv使用UnityStereoTransformScreenSpaceTex
。
Shader輔助函數(shù)
下列函數(shù)可以在此文件中找到:“Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl”.
頂點轉(zhuǎn)換函數(shù)
內(nèi)置管線 | URP |
---|---|
float4 UnityObjectToClipPos(float3 pos) | float4 TransformObjectToHClip(float3 positionOS) |
float3 UnityObjectToViewPos(float3 pos) | TransformWorldToView(TransformObjectToWorld(positionOS)) |
法線轉(zhuǎn)換函數(shù)
內(nèi)置管線 | URP |
---|---|
float4 UnityObjectToWorldNormal(float3 pos) | float4 TransformObjectToWorldNormal(float3 normalOS) |
通用輔助函數(shù)
內(nèi)置管線 | URP | |
---|---|---|
float3 UnityWorldSpaceViewDir(float4 v) | GetCameraPositionWS() - i.worldPos | |
float3 UnityObjectToWorldDir(float4 v) | TransformObjectToWorldDir(real3 dirOS) | |
float3 ObjSpaceViewDir(float4 v) | 移除了份乒,可以使用TransformWorldToObject(GetCameraPositionWS()) - objectSpacePosition ; |
|
float2 ParallaxOffset(half h恕汇,half height,half3 viewDir) | 移除了或辖●ⅲ可以從UnityCG.cginc復(fù)制過來 | |
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復(fù)制過來 | |
float DecodeFloatRGBA(float4 enc) | 移除了缺谴。可以從UnityCG.cginc復(fù)制過來 | |
float2 EncodeFloatRG(float v) | 移除了耳鸯∈祝可以從UnityCG.cginc復(fù)制過來 | |
float DecodeFloatRG(float2 enc) | 移除了∑模可以從UnityCG.cginc復(fù)制過來 | |
float2 EncodeViewNormalStereo(float3 n) | 移除了煌集〖酥可以從UnityCG.cginc復(fù)制過來 | |
float3 DecodeViewNormalStereo(float4 enc4) | 移除了捌省。可以從UnityCG.cginc復(fù)制過來 | |
TANGENT_SPACE_ROTATION |
前向渲染輔助函數(shù)
內(nèi)置管線 | 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”
|
屏幕空間輔助函數(shù)
內(nèi)置管線 | URP | |
---|---|---|
float4 ComputeScreenPos(float4 clipPos) | float4 ComputeScreenPos(float4 positionCS) | Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl” |
float4 ComputeGrabScreenPos(float4 clipPos) | 移除了 |
頂點照明輔助函數(shù)↑
內(nèi)置管線 | 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”中找到很多工具函數(shù)纲缓。
內(nèi)置著色器變量
除了光照相關(guān)的變量外,其他的變量名都基本沒變
照明↑
內(nèi)置管線 | 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中污筷,其他光源存儲在數(shù)組/緩沖區(qū)中(取決于平臺)工闺。使用Light GetAdditionalLight(uint i, float3 positionWS) 獲取額外光源信息 |
Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl” |
unity_4LightAtten0 | 在URP中,其他光源存儲在數(shù)組/緩沖區(qū)中(取決于平臺)。使用Light GetAdditionalLight(uint i, float3 positionWS) 獲取額外光源信息 |
Include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl” |
unity_LightColor | 在URP中陆蟆,其他光源存儲在數(shù)組/緩沖區(qū)中(取決于平臺)雷厂。使用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” |
如果要使用循環(huán)所有其他燈光GetAdditionalLight(...)
,GetAdditionalLightsCount()
可以使用來查詢其他燈光計數(shù)叠殷。
其他
陰影
有關(guān)陰影的更多信息改鲫,“Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl”
內(nèi)置管線 | URP | |
---|---|---|
UNITY_SHADOW_COORDS(x) | 移除了。DIY林束,例如float4 shadowCoord : TEXCOORD0;
|
|
TRANSFER_SHADOW(a) | a.shadowCoord = TransformWorldToShadowCoord(worldSpacePosition) | 啟用cascades時像棘,對片段執(zhí)行此操作以避免視覺鬼影 |
SHADOWS_SCREEN | 移除了。不支持壶冒。 |
霧
有關(guān)霧的更多信息缕题,“Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl”.
內(nèi)置管線 | 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); |
深度
要使用相機(jī)深度紋理瓶摆,需要include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl” ,然后會自動聲明_CameraDepthTexture
性宏,也會包含輔助函數(shù)SampleSceneDepth(...)
和LoadSceneDepth(...)
群井。
內(nèi)置管線 | 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” |
其他中的其他
內(nèi)置管線 | 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” |
后處理/視覺特效
URP不支持OnPreCull
,OnPreRender
酵使,OnPostRender
和OnRenderImage
這些方法荐吉。URP支持OnRenderObject
和OnWillRenderObject
,但是如果在URP中使用你可能會發(fā)現(xiàn)問題口渔。因此样屠,如果你曾經(jīng)在舊管線創(chuàng)建視覺效果時使用它們,那么現(xiàn)在你需要學(xué)習(xí)新方法了缺脉。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
是受支持的,但是攻礼,如果你需要在其中執(zhí)行渲染調(diào)用(例如业踢,水反射/折射),它將無法正常工作礁扮。調(diào)用Camera.Render()
知举,你將看到以下消息:
Recursive rendering is not supported in SRP (are you calling Camera.Render from within a render pipeline?)
翻譯過來就是:
SRP不支持遞歸渲染(你是從渲染管道中調(diào)用Camera.Render嗎瞬沦?)
在這種情況下,URP中應(yīng)該將OnWillRenderObject
替換為begin/endCameraRendering
(如上面的例子)雇锡,并調(diào)用RenderSingleCamera()
蛙埂,而不是 Camera.Render()
。更改上面的示例遮糖,你將獲得以下內(nèi)容
void MyCameraRendering(ScriptableRenderContext context, Camera camera)
{
...
if(camera == myEffectCamera)
{
...
UniversalRenderPipeline.RenderSingleCamera(context, camera);
}
...
}
使用后處理的另一種方法是使用ScriptableRendererFeature
绣的。這篇文章很好地解釋了使用RenderFeature的描邊效果。ScriptableRendererFeature
可以讓你將ScriptableRenderPass(es)
注入到渲染管線的不同階段欲账,因此是創(chuàng)建后處理效果的強(qiáng)大工具屡江。注入位置可以包含以下:
BeforeRendering
BeforeRenderingShadows
AfterRenderingShadows
BeforeRenderingPrepasses
AfterRenderingPrePasses
BeforeRenderingOpaques
AfterRenderingOpaques
BeforeRenderingSkybox
AfterRenderingSkybox
BeforeRenderingTransparents
AfterRenderingTransparents
BeforeRenderingPostProcessing
AfterRenderingPostProcessing
AfterRendering
這是ScriptableRendererFeature
使用自定義材質(zhì)執(zhí)行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”來創(chuàng)建一個ScriptableRendererFeature
。你創(chuàng)建的功能必須添加到你的中ForwardRenderer
赛不。為此惩嘉,選擇ForwardRenderer
,單擊Add Renderer Feature踢故,然后選擇要添加的功能文黎。你可以在Inspector中公開屬性,例如上面的例子中包含了一個材質(zhì)球?qū)傩浴?/p>
結(jié)語
由于Unity和URP殿较、SRP都在快速迭代更新耸峭,本文也會不定時更新。如果有問題淋纲,你可以在本文原文中評論劳闹,也可以通過微信:zhz11235或者QQ:329541945找到我。