unity渲染管线及升级URP

Posted 我要吐泡泡了哦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity渲染管线及升级URP相关的知识,希望对你有一定的参考价值。

unity渲染管线及升级URP

  • 22.5.31 发现这篇只能查找参考用,实际改urp看了用处不大,urp管线下pbrshader流程看新写的URP实现PBR shader

一,unity渲染管线简介

Unity引擎的渲染管线主要分为"渲染核心库"与"渲染策略"两个部分, “渲染核心库”是Unity把基于OpenGL/DirectX把渲染相关的接口函数封装成API,这部分Unity引擎写好后作为核心的API渲染库。”渲染策略”指的是Unity引擎绘制整个游戏场景的时候,如何处理多相机,多光源,阴影投射,物体绘制,雾,自发光等。这个就叫做渲染策略,渲染管线基于一种渲染策略,调用渲染核心库中的API,把整个游戏场景绘制出来。

渲染管线通过执行 剔除、渲染、后处理 来获取场景的内容,并将这些内容显示在屏幕上。不同的渲染管线具有不同的功能和性能特征,并且适用于不同的游戏、应用程序和平台。

  • unity提供三种渲染管线,内置渲染管线、通用渲染管线(URP)和高清渲染管线(HDRP),也可以通过unity的可编程渲染管线(Scriptable Render Pipeline,SRP) API 来完全自定义渲染管线。
    1. 内置渲染管线是unity默认的,自定义选项有限,是向前渲染(支持任意多光源,每个光照各走一遍pass性能差)。(可以用CommandBuffer和回调进行骚操作,版稳定性不好死板)
    2. URP(Universal Render Pipeline)「前身LWRP–轻量级渲染管线」是用SRP写的非侵入式轻量级自定义渲染管线,专注性能,比如只支持几个光源但能在同一个pass计算;除了有特殊需求选它就对了。
    3. HDRP可以做更多复杂算法,可以在高端平台上(PC主机等)输出高保真图形,支持全局光照、光线跟踪、子面散射等,但想得到好效果需要大量贴图,人力预算up!「因为这次主要学习URP,HDRP这里就简单了解下。也有人说HDRP太复杂了,不如直接用ue。」

  • 其主要区别在于渲染策略,不同的渲染策略对应的shader不一样,之前学习的shader写法都是针对向前渲染的,如果切换成URP则shader包需要重新开发。可编程渲染管线shader语法结构还是shader lab,开发语言使用HLSL,有的也支持shader graphic。

二,通用渲染管线URP

  • URP相对内置管线的优点:

    1. 开源。
    2. 渲染路径为单Pass Forward Rendering,DrawCall数量大大下降(支持动态灯光数量受GPU限制),阴影处理性能也好很多。(内置多光源时需要FowardAdd Pass,因此以前后用烘焙light map)
    3. 拓展性好,拓展入口相当于CommandBuffer的可视化操作;新设计取代了GrabPass结构,可以提供Opaque Texture。
    4. SRP Batcher,对shader的批处理,只要着色器变体一样的都一起批处理。并将shader材质数据保存在Gpu中用时绑定,而不是每次用时从缓冲区上传,以此减少渲染状态设置的CPU开销—比如glUniform4fv等设置。「变体是指shader中通过关键字设置的不同逻辑功能或者shader设置参数不同的,就是不同变体」
  • 与默认管线功能对比见URP与内置渲染管线功能对照表

  • URP与unity版本对应:

三,shader升级URP

1,Builtin RP和URP中内置Shader 的对应

2,总体结构

  1. 在SubShader的Tags中添加"RenderPipeline" = “UniversalPipeline"表示该SubShader是给URP用的「HDRP设置为"HDRenderPipeline”」
  2. 并使用HLSL的宏替代CG:
Built-inURP
CGPROGRAM、HLSLPROGRAMHLSLPROGRAM
ENDCG、ENDHLSLENDHLSL
CGINCLUDE、HLSLINCLUDEHLSLINCLUDE
  • HLSL是URP的首选语言,但URP也支持CG语言,因此CGPROGRAM等也能用,就是和SRP Batcher 不兼容。
  1. 在Properties中声明的属性需要再在HLSL 代码中用CBUFFER声明(为了SRP Batcher):
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);

CBUFFER_START(UnityPerMaterial)
    half4 _BaseColor;
    float4 _BaseMap_ST;
CBUFFER_END
  1. fixed都不支持了,改为half或者float。

3,include

  • include对应:
\\Built-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.cgincURP内没有,可以参考该github项目
  • 示例
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  • URP其他常用include:SpaceTransforms.hlsl、ShaderVariablesFunctions.hlsl、Common.hlsl、Input.hlsl、Color.hlsl、DeclareDepthTexture.hlsl、DeclareOpaqueTextue.hlsl
  • Core.hlsl可以直接引用,UnityInput.hlsl、UnityInstancing.hlsl、SpaceTransforms.hlsl等需要带上前缀,防止重定义。

4,光照模式LightMode

  • Builtin RP和URP对应的光照模式:
Built-inURP
ForwardBaseUniversalForward
ForwardAdd移除,开启关键字_ADDITIONAL_LIGHTS解决
Deferred 以及相关URP12.0支持
Vertex and related移除
ShadowCasterShadowCaster
MotionVectors暂不支持
  • URP新增的:DepthOnly、Meta(用于烘焙光照贴图)、Universal2D(用于2D的前向渲染)、UniversalGBuffer(延迟渲染用)、UniversalForwardOnly(延迟渲染中表示该pass用向前渲染)。

5,变体Variants

  • 类似内置管线用multi_compile_fwdbase编译ForwardBasePass;URP涉及批处理的变体,可以用#pragma multi_compile添加关键字设置:
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE

6,预定义宏

辅助宏

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)
UNITY_SHADOW_COORDS(x)float4 shadowCoord : TEXCOORD##x
TRANSFER_SHADOW(a)a.shadowCoord = TransformWorldToShadowCoord(worldSpacePosition)
SHADOWS_SCREEN移除了

纹理采样器声明

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)
UNITY_INITIALIZE_OUTPUT(name)ZERO_INITIALIZE(name)

光照、雾

Built-inURP
UNITY_LIGHTMODEL_AMBIENThalf3(unity_SHAr.w,unity_SHAr.w,unity_SHAr.w);
UNITY_FOG_COORDS(x)用float fogCoord : TEXCOORD##x;
UNITY_TRANSFER_FOG(o, outpos)o.fogCoord = ComputeFogFactor(clipSpacePosition.z);
UNITY_APPLY_FOG(coord, col)color = MixFog(color, i.fogCoord);

7,辅助函数

变换函数

Built-inURP
float4 UnityObjectToClipPos(float3 pos)float4 TransformObjectToHClip(float3 positionOS)
float4 UnityWorldToClipPos(float3 pos)float4 TransformWorldToHClip(float3 positionWS)
float3 UnityObjectToViewPos(float3 pos)TransformWorldToView(TransformObjectToWorld(positionOS))
float3 UnityObjectToWorldNormal(in float3 norm)float3 TransformObjectToWorldNormal(float3 normalOS,bool doNormalize = true)
float3 UnityWorldSpaceViewDir (float4 v)_WorldSpaceCameraPos.xyz - positionWS
float3 UnityObjectToWorldDir (float4 v)float3 TransformObjectToWorldDir(real3 dirOS)

通用辅助函数

Built-inURP
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)
fixed3 DecodeLightmap (fixed4 color)real3 DecodeLightmap(real4 encodedIlluminance, real4 decodeInstructions)
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-inURP
float3 WorldSpaceLightDir(float4 v)_MainLightPosition.xyz - TransformObjectToWorld(objectSpacePosition)
float3 ObjSpaceLightDir (float4 v)TransformWorldToObject(_MainLightPosition.xyz) - objectSpacePosition
float3 Shade4PointLights (…)用half3 VertexLighting(float3 positionWS, half3 normalWS)

屏幕空间

Built-inURP
float4 ComputeScreenPos (float4 clipPos)float4 ComputeScreenPos(float4 positionCS)
float4 ComputeGrabScreenPos (float4 clipPos)移除了

顶点光照

Built-inURP
float3 ShadeVertexLights (float4 vertex, float3 normal)用half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w) + VertexLighting(…)

深度

可直接使用 _CameraDepthTexture来采样深度纹理,也可使用SampleSceneDepth(…) 和 LoadSceneDepth(…)来采样。

Built-inURP
LinearEyeDepth (sceneZ)LinearEyeDepth(sceneZ, _ZBufferParams)
Linear01Depth (sceneZ)Linear01Depth(sceneZ, _ZBufferParams)

其他

Built-inURP
shadeSH9 (float4 normal)SampleSH(normal)
unity_ColorSpaceLuminance用Luminance()

7,内置变量

Built-inURP
_LightColor0_MainLightColor
_WorldSpaceLightPos0_MainLightPosition
_LightMatrix0移除了。目前尚不支持
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0在URP中,其他光源存储在数组/缓冲区中(取决于平台)。使用Light GetAdditionalLight(uint i, float3 positionWS)获取光源信息
unity_4LightAtten0同上
unity_LightColor同上)
unity_WorldToShadowfloat4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1] 或者_AdditionalLightsWorldToShadow[MAX_VISIBLE_LIGHTS]

使用循环所有其他灯光–GetAdditionalLight(),查询其他灯光计数–GetAdditionalLightsCount()。

8,后处理

  • URP不支持OnPreCull,OnPreRender,OnPostRender和OnRenderImage。
  • 支持OnRenderObject和OnWillRenderObject,但旧管线直接用有问题,需要改写。
  • UPR函数+示例:
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)
    
    ...
    UniversalRenderPipeline.RenderSingleCamera(context, camera);
    
    ...

参考资料

  1. unity官方文档
  2. 知乎-Unity URP/SRP 渲染管线浅入深出
  3. From Built-in to URP
  4. 内置到URP官方切换文档

unity urp 渲染管线顶点偏移的实现

这里我是通过法线对顶点进行偏移

如果面与面之间的点不是公用的,会出现屏幕中立方体的效果,球则没有这个问题。所以使用顶点偏移的时候需要注意一下。
我实现的是在模型空间进行顶点偏移,大家按自己的需求实现

接下来,代码:

Shader "URP/VertexOffset"

    Properties
    
        [MainTexture] _BaseMap ("Albedo", 2D) = "white"  
        [MainColor] _BaseColor ("Color", Color) = (1, 1, 1, 1)
        
        _Cutoff ("Alpha Cutoff", Range(0.0, 1.0)) = 0.5

        _VertexOffset ("顶点偏移", Float) = 0
        
        _Cull ("Cull", Int) = 2

    

    SubShader
    
        Tags  "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "Lit" "IgnoreProjector" = "True" "ShaderModel" = "4.5" 
        LOD 300

        // ------------------------------------------------------------------
        //  Forward pass. Shades all light in a single pass. GI + emission + Fog
        Pass
        
            Tags  "LightMode" = "UniversalForward" 
            Cull[_Cull]

            HLSLPROGRAM

            #pragma exclude_renderers gles gles3 glcore
            #pragma target 4.5

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma instancing_options renderinglayer
            #pragma multi_compile _ DOTS_INSTANCING_ON

            #pragma vertex LitPassVertex
            #pragma fragment LitPassFragment

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            //需要光照系统时增加此引入
            // #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attributes
            
                float4 positionOS : POSITION;
                float3 normalOS : NORMAL;
                float4 tangentOS : TANGENT;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            ;

            struct Varyings
            
                float2 uv : TEXCOORD0;
                float4 positionCS : SV_POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            ;

            TEXTURE2D(_BaseMap);        SAMPLER(sampler_BaseMap);

            CBUFFER_START(UnityPerMaterial)
            half4 _BaseColor;
            half4 _BaseMap_ST;
            half _Cutoff;
            half _VertexOffset;
            CBUFFER_END

            // Used in Standard (Physically Based) shader
            Varyings LitPassVertex(Attributes input)
            
                Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                //通过法向偏移顶点
                half3 positionOS = input.positionOS.xyz;
                positionOS += input.normalOS * _VertexOffset;

                output.positionCS = TransformObjectToHClip(positionOS);
                output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);

                return output;
            

            half4 LitPassFragment(Varyings input) : SV_Target
            
                UNITY_SETUP_INSTANCE_ID(input);
                //---------------输入数据-----------------
                float2 UV = input.uv;

                half4 color = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv) * _BaseColor;
                clip(color.r - _Cutoff);

                return color;
            
            ENDHLSL

        

    

    FallBack "Hidden/Universal Render Pipeline/FallbackError"


以上是关于unity渲染管线及升级URP的主要内容,如果未能解决你的问题,请参考以下文章

Unity教程:URP渲染管线实战教程系列

[游戏开发]Unity SRP 学习

unity 2019 hdrp 管线 制作天空盒

Unity渲染管线流程

在Unity里添加2D法线贴图 NormalMap

[Unity Shader] 渲染管线流程