Unity 内置渲染管线转URP

一、CG 替换 HLSL

  1. 未使用光照计算的shader升级后不做修改仍然可以使用,但是可能会不兼容SRP Batcher,所以仍然需要修改,使用了光照计算的shader必须要修改。

  2. SubShader的Tags中增加 “RenderPipeline”="UniversalPipeline"声明

  3. 要保证多pass物体正确绘制,需要确保有个pass打上 UniversalForward 的tag,其余pass有 SRPDefaultUnlit的tag也行,没有也行。

  4. HLSLPROGRAM 替换 CGPROGRAM
    HLSLINCLUDE 替换 INCLUDE
    ENDHLSL 替换 ENDCG

  5. fixed 替换为:half 或者 float

  6. FallBack
    FallBack “Hidden/Universal Render Pipeline/FallbackError”

  7. LightMode

    "LightMode" 要改为URP支持的模式, 比如   
    
    "LightMode" = "Forward"   
    
    替换为   
    
    "LightMode" = "UniversalForward"
    
    其他常用URP的mode类型:
    
    "LightMode" = "Universal2D"
    
    "LightMode" = "Meta"
    
    "LightMode" = "DepthOnly"
    
    "LightMode" = "ShadowCaster"
    
  8. 使用URP ShaderLibrary引用Core.hlsl替换内置渲染管线中的UnityCG.cginc

    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"  
    替换  
    #include "UnityCG.cginc"
    

    其他库类似:

    #include "Lighting.HLSLinc"
    替换为:
    #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
    #include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl"
    
    阴影:
    #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
    
  9. 内置结构体、内置函数 和矩阵

    appdata_full 这种结构体不能用了,如何一一替换我就不举例了
    内置函数 和矩阵需要查阅Packages/Universal RP/ShaderLibrary/UnityInput
    内置结构体、函数需要查阅
    Packages/Universal RP/ShaderLibrary/Input
    Packages/Universal RP/ShaderLibrary/Core

  10. 使用 TransformObjectToHClip 替换 UnityObjectToClipPos
    或者改成如下写法:

    Varyings vert(Attributes IN) {
        Varyings OUT;
     
        VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
        OUT.positionCS = positionInputs.positionCS;
        // Or this :
        //OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
     
        OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
        OUT.color = IN.color;
        return OUT;
    }
    

    GetVertexPositionInputs 计算不同坐标系中的位置,结果包含世界坐标系坐标,观察坐标系坐标,裁剪坐标系坐标,标准设备坐标系坐标,未使用到的坐标不会被包含到编译出的shader中,所以不会有额外的不必要的计算量。TRANSFORM_TEX 在内置渲染管线和URP中都可以用。GetVertexNormalInputs 可以将法线和切线从对象坐标系变换到世界坐标系。也可以用 TransformObjectToWorldNormal(IN.normalOS) 代替。

    VertexNormalInputs normalInputs = GetVertexNormalInputs(IN.normalOS, IN.tangentOS);

  11. 在URP中纹理和采样器的定义改成如下写法:

    	// 将_BaseMap声明为Texture2D对象
    	TEXTURE2D(_MainTex);
    	// 将_BaseMap声明为Texture2D对象
    	SAMPLER(sampler_MainTex);
    	
    	float4 frag (v2f i) : SV_Target
    	{
    	    float4 col = SAMPLE_TEXTURE2D(_BaseMap,sampler_BaseMap, i.texcoord);
    	    return col;
    	}
    
  12. 区分 multi_compile 和 shader_feature,剥离不需要的编译选项,减少shader变体。

    https://zhuanlan.zhihu.com/p/77043332

    https://www.jianshu.com/p/8750704a2f4c

  13. URP不支持表面着色器,URP ShaderLibrary 中处理光照计算的函数在 Lighting.hlsl中,该文件需要手动include。

    //这些编译指令用于接收阴影
    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    #pragma multi_compile _ _SHADOWS_SOFT
     
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    
  14. 当使用Lighting.hlsl支持光照和阴影,应该添加下面的编译选项,如果没有定义,ShaderLibrary会跳过一些计算。

    // Main Light Shadows
    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
     
    // Additional Lights & Shadows
    #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
    #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
     
    // Soft Shadows
    #pragma multi_compile _ _SHADOWS_SOFT
     
    // Other (Mixed lighting, baked lightmaps, fog)
    #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
    #pragma multi_compile _ DIRLIGHTMAP_COMBINED
    #pragma multi_compile _ LIGHTMAP_ON
    #pragma multi_compile_fog
     
    // Supporting shadows will also require passing a positionWS, 
    // and shadowCoord into the fragment shader, again you'll have 
    // to see the Lighting sections for actual examples.
    

    接受投影:

    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    
    float4 frag (v2f i) : SV_Target
    {
       float4 shadowCoords = TransformWorldToShadowCoord(i.worldPos);
       Light mainLight = GetMainLight(shadowCoords);
       //阴影实时遮挡
       half shadow = mainLight.shadowAttenuation;
       return shadow;
    }
    
    被投影:
    
       //新加一个pass
       UsePass "Universal Render Pipeline/Lit/ShadowCaster"
    
  15. 为了处理雾,使用ComputeFogFactor 和 MixFog 函数。

    #pragma multi_compile_fog
     
    struct Varyings {
        ...
        half fogFactor : TEXCOORD5;
        // or whatever unused texcoord
        // if none are unused pack it together with a half3 or something
    }
    ...
    
    // In the vertex shader :
    half fogFactor = ComputeFogFactor(positionInputs.positionCS.z);
     
    // In the fragment, just before returning the color :
    color.rgb = MixFog(color.rgb, IN.fogFactor);
    
    

二、多Pass问题:

在URP中是使用的single-pass前向渲染,也就是单Pass。
转URP的时候我们会发现 以前多Pass的shader会异常,只会渲染第一个Pass。

如果我们确实需要多Pass怎么办?

我们可以通过设置第一个Pass的LightMode为:UniversalForward就行了。

例如:

Shader "lcl/Shader"   
{      
	Properties       
	{      
		_Color("Color", Color) = (1,1,1,1)
		_MainTex("Albedo", 2D) = "white" {}      
	}    
	SubShader {
		LOD 100
		Lighting Off
		Pass
		{

			Tags { "LightMode"="UniversalForward"}
	        ...
		}
		Pass {  
			Tags {"LightMode"="SRPDefaultUnlit"}
			...
        }
} 

但是不推荐多Pass渲染,因为会打断 SRP Batcher,使DrawCall增加。(当然 如果没使用SRP Batcher则不影响)

具体什么是SRP Batcher可以参考这里

https://zhuanlan.zhihu.com/p/165574008
https://zhuanlan.zhihu.com/p/165388825

·如果确实需要可以通过RendererFeatures实现多Pass效果

三、兼容SRP Batcher:

首先需要勾选 SRP Batcher。

quicker_485ad9c0-c22f-469a-9a0f-19f77fe3813b.png

shader代码修改:

Shader中所有的内置属性例如unity_ObjectToWorldunity_SHAr等,都要在一个名为UnityPerDraw的CBUFFER中声明;
所有的Material属性都要在一个名为UnityPerMaterial的CBUFFER中声明。

CBUFFER_START(UnityPerMaterial)
//Properties
CBUFFER_END

CBUFFER_START(UnityPerDraw)
    float4x4 unity_ObjectToWorld;
CBUFFER_END

例如:

Properties
{
_Color1 ("Color 1", Color) = (1,1,1,1)
_Color2 ("Color 2", Color) = (1,1,1,1)
}
 
//原本的写法
//float4 _Color1;
//float4 _Color2;
 
//兼容SRP Batcher的写法
CBUFFER_START(UnityPerMaterial)
float4 _Color1;
float4 _Color2;
CBUFFER_END


CBUFFER_START(UnityPerDraw)
    float4x4 unity_ObjectToWorld;
CBUFFER_END

如果shader报错:Shader error in ‘Unlit/SampleUnlit’: redefinition of ‘unity_ObjectToWorld’,重复定义,如果自己的shader代码里面没有,那么就是引入了其他的库文件里面包含了该变量。

最后,我们看Shader的面板,如果出现了类似的提示:

quicker_f0879be0-abd4-405c-af88-1fcf889d98df.png

则表示 该属性 未包含在 CBUFFER_START(UnityPerMaterial) 里面。

注意:如果Shader使用了多Pass渲染,则会打断 SRP Batcher。

参考链接:

https://zhuanlan.zhihu.com/p/254810253

https://blog.csdn.net/wannaconquer/article/details/114092927

  • 11
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值