URP入门

URP基础

URP由来

Unity内置渲染管线Build-in Render Pipeline

由于该管线上要适配高画质主机游戏

下要适配古早移动设备,这使它的内部有非常多的冗杂

因此

需要针对某一平台发布特定的管线,即Universal Render Pipeline

此外

Unity早起推出High Definition RP和Light Weight RP

但大家觉得后者太low,就不用,但Unity知道后者才是更优秀的,因此更名为URP

这些都是可编程渲染管线:Scriptable RP

URP的使用

1.Shader Graph

虽然是连连看,但他会很好地帮助我们写Shader

相当于一个快速写代码组件,可以验证脑海中的猜想是否可行

如果可行,就可以把Graph写成Shader了

2.最简单Shader-Unlit

写法和Build-in管线的普通Shader类似

查看代码
Shader "MyURP/Unlit"
{
    Properties
    {
        _Color("Color", color) = (1,1,1,1)
    }
    SubShader
    {
        Tags
        {
            "RenderPipeline"="UniversalPipeline"
        }
        Pass
        {
            HLSLPROGRAM//CG->HLSL
            #pragma vertex vert
            #pragma fragment frag
            //UnityCG.cginc->↓
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            //命名更规范,OS:ObjectSpace,WS:WorldSpace,CS:ClipSpace
            struct Attributes
            {
                float3 positionOS : POSITION;
            };

            struct Varyings
            {
                float4 positionCS : SV_POSITION;
            };

            //可以使用SRP的特性-常量缓冲区优化数据
            //自定义的常量缓冲区会放到UnityPerMaterial缓冲区中
            //Unity内部定义的常量,如旋转矩阵、渲染平台参数、相机位置、主光源方向等,会放到UnityPerDraw缓冲区中
            CBUFFER_START(UnityPerMaterial)
            half4 _Color;
            CBUFFER_END

            Varyings vert (Attributes v)
            {
                Varyings o = (Varyings)0;
                float3 positionWS = TransformObjectToWorld(v.positionOS);
                o.positionCS = TransformWorldToHClip(positionWS);
                return o;
            }

            half4 frag (Varyings i) : SV_TARGET
            {
                half4 col = _Color;
                col.a = 1;
                return col;
            }
            ENDHLSL
        }
    }
    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}
//最后一点可能要注意的是Unity更新了深度引动模式:Depth Priming Mode
//即非透明物体都需要一个深度Pass来帮助渲染
//此处没有写是为了最简化
//解决方法一:UsePass "Universal Render Pipeline/Unlit/DepthOnly
//解决方法二:在RendererData中关闭该技术

SRP Batch

介绍

可编程渲染管线合批功能,是一个很强的性能优化功能

每一个同类Shader都使用显存中同一个区域的数据

在往深处看,就是在编译时,会根据不同平台去生成一个常量缓冲区,例如 GLES2 就没有这东西

具体效果直接看官网就行了

要求和使用

1.静态网格,动态的例如蒙皮网格就不能使用

2.Shader支持SRP合批,CBUFFER,

3.

生成5个材质,用的同一个Shader

未开启SRP Batching前就是5个批次

开启后就是一个批次不过是5个DrawCall,但问题不大

回顾其他合批,分析不同点

静态合批:场景烘焙,不同网格,同一材质球(参数一样)

动态合批:顶点、属性显示,不同网格,同一材质球(参数一样)

GPU实例化:同一网格,同一材质球(参数不一样)

SRP合批:Build-in无法使用,不同网格,不同材质球,同一Shader

内存处理

Build-in渲染管线运行逻辑

1.CPU要渲染某一物体时,去内存中拿该物体的数据,分为两部分,
位置、组件、网格、材质球等,
另一是该物体身上的所有材质球的属性参数,贴图、map等

2.CPU拿到数据后,将部分渲染需要用到的数据发送给显存,在显存中生成一个个常量缓冲区

3.Shader运行时再去这一个个常量缓冲区拿数据

URP中就是把Build-in中拿的两部分数据分开了

1.在显存中开一个比较大Buffer群组,去存放物体旋转矩阵、相机位置、主光源方向等内部参数,每一个物体都会有一个Buffer

2.CPU另开一块,专门去处理材质球,当某材质球被初始化或者被修改时会调用

3.就是传到专属于该材质的Buffer中

4.Shader运行时去Buffer群组中和目标材质Buffer中拿数据

纹理与采样分离

对象声明的变化
 //纹理的定义,背后是平台的区分,例如GLES2就是sampler2D _XXX,其他的是Texture2D _XXX
TEXTURE2D(_Texture);
//采样器的定义,背后是平台的区分,例如GLES2就是空,其他的会生成一个采样器SamplerState sampler_Texture
SAMPLER(sampler_Texture);
纹理采样的变化
 //GLES2和默认管线的采样操作:tex2D(_Texture, i.uv);
//纹理采样,背后也是平台的区分,其他的是_Texture.Sample(sampler_Texture, i.uv);
half4 tex = SAMPLE_TEXTURE2D(_Texture, sampler_Texture, i.uv);

采样器是什么

就是采样贴图的工具,但可以自定义如何去采样

分离的作用

旧的渲染管线下,定义了贴图,采样也会同时被确认,如果需要对该贴图进行其他的采样,就需要特别的写算法

因此需要由不同的采样器其采样同一张贴图,以此来得到不同的效果

使用方法

传统采样设置是在Inspector面板设置的

但这样采样就会被限制死了

因此需要采样器介入

SAMPLER(smp);

其中smp的命名就定义了采样方式

第一个下划线后的为过滤模式 如:xxx_linear就定义为线性采样

第二个下划线后面的为重复方式 如:xxx_xxx_clamp就定义为非重复模式采样

倘若为_linear_clampU_repeatV就定义为U(x)方向不重复,V(y)方向重复的采样模式

URP模板

URP手册地址taecg/ShaderReference: 针对Unity的Shader参考大全 (github.com)

Editor/Data/Resources/ScriptTemplates/94-Shader__URP-NewURPShader.shader.txt
 Shader "MyURP/XXX"
{
    Properties
    {
        _BaseColor("Base Color",color) = (1,1,1,1)
        _BaseMap("BaseMap", 2D) = "white" {}
    }
 
    SubShader
    {
        Tags
        {
            "Queue"="Geometry"
            "RenderType" = "Opaque"
            "IgnoreProjector" = "True"
            "RenderPipeline" = "UniversalPipeline"
        }
        LOD 100
 
        Pass
        {
            Name "XXX"

            HLSLPROGRAM

            // Required to compile gles 2.0 with standard srp library
            #pragma prefer_hlslcc gles
            #pragma exclude_renderers d3d11_9x
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
 
            struct Attributes
            {
                float4 positionOS       : POSITION;
                float2 uv               : TEXCOORD0;
            };
 
            struct Varyings
            {
                float4 positionCS       : SV_POSITION;
                float2 uv               : TEXCOORD0;
                float fogCoord          : TEXCOORD1;
            };
 
            CBUFFER_START(UnityPerMaterial)
            half4 _BaseColor;
            float4 _BaseMap_ST;
            CBUFFER_END
            TEXTURE2D (_BaseMap);SAMPLER(sampler_BaseMap);
 
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;
 
                o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
                o.uv = TRANSFORM_TEX(v.uv, _BaseMap);
                o.fogCoord = ComputeFogFactor(o.positionCS.z);
 
                return o;
            }
 
            half4 frag(Varyings i) : SV_Target
            {
                half4 c;

                half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv);
                c = baseMap * _BaseColor;
                c.rgb = MixFog(c.rgb, i.fogCoord);

                return c;
            }
            ENDHLSL
        }
    }
}

URP案例

能量罩

最终代码
 Shader "MyURP/EnergyShield"
{
    Properties
    {
        [Header(High Light)]
        _HighLightFade("High Light Fade", Range(1, 10)) = 10
        _HighLightColor("High Light Color", color) = (1,1,1,1)

        [Header(Fresnel)]
        [PowerSlider(3)]_FresnelPow("Fresnel Pow", Range(1, 15)) = 7
        _FresnelColor("Fresnel Color", color) = (1,1,1,1)

        [Header(Flow Distort)]
        _FlowTiling("Flow Tiling", float) = 6
        _FlowDistort("Flow Distort", Range(0,1)) = 0.4
        _FlowMap("Base Map", 2D) = "white" {}
    }
 
    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "RenderType" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderPipeline" = "UniversalPipeline"
        }
        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha
 
        Pass
        {
            Name "EnergyShield"

            HLSLPROGRAM

            // Required to compile gles 2.0 with standard srp library
            #pragma prefer_hlslcc gles
            #pragma exclude_renderers d3d11_9x
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
 
            struct Attributes
            {
                float4 positionOS       : POSITION;
                half3 normalOS          : NORMAL;
                float2 uv               : TEXCOORD0;
            };
 
            struct Varyings
            {
                float4 positionCS       : SV_POSITION;
                float4 uv               : TEXCOORD0;
                float fogCoord          : TEXCOORD1;
                half positionVS_Z       : TEXCOORD2;
                half3 normalWS          : TEXCOORD3;
                half3 viewWs            : TEXCOORD4;
            };
 
            CBUFFER_START(UnityPerMaterial)
            half _HighLightFade;
            half4 _HighLightColor;
            half _FresnelPow;
            half4 _FresnelColor;
            half _FlowTiling;
            half _FlowDistort;
            float4 _FlowMap_ST;
            CBUFFER_END
            TEXTURE2D (_FlowMap);SAMPLER(sampler_FlowMap);
            TEXTURE2D (_CameraDepthTexture);SAMPLER(sampler_CameraDepthTexture);
            TEXTURE2D (_CameraOpaqueTexture);SAMPLER(sampler_CameraOpaqueTexture);
 
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;
 
                o.uv.xy = v.uv;
                o.uv.zw = TRANSFORM_TEX(v.uv, _FlowMap);

                //由于需要获取深度值(离相机越远越大),就需要View空间下的Z值
                float3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
                float3 positionVS = TransformWorldToView(positionWS);
                //由于都算到这了,TransformObjectToHClip内部也要做这么些事,不如节省一下,把值拿来用
                o.positionCS = TransformWViewToHClip(positionVS);
                o.positionVS_Z = -positionVS.z;

                o.normalWS = TransformObjectToWorldNormal(v.normalOS);
                o.viewWs = normalize(_WorldSpaceCameraPos - positionWS);
 
                return o;
            }
 
            half4 frag(Varyings i) : SV_Target
            {
                half4 c = 0;

                //---靠近物体部分高光---
                //获取片段对应深度图中像素在观察空间下的深度,0~正无穷
                float2 screenUV = i.positionCS.xy / _ScreenParams.xy;
                half4 depthMap = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, screenUV);
                //将值限制为0~1,符合View空间
                half depth = LinearEyeDepth(depthMap.r, _ZBufferParams);
                //计算边缘高光
                half delta = (depth - i.positionVS_Z) * _HighLightFade;
                half highLight = saturate(1 - delta);
                c += highLight * _HighLightColor;
                //---------------------

                //-----菲尼尔外发光-----
                //pow(max(0, dot(N,V)), Intensity)
                half3 N = i.normalWS;
                half3 V = i.viewWs;
                half NdotV =  1 - saturate(dot(N, V));
                half fresnel = pow(abs(NdotV), _FresnelPow);
                c += fresnel * _FresnelColor;
                //---------------------

                //--------扭曲流动--------
                half baseMap = SAMPLE_TEXTURE2D(_FlowMap, sampler_FlowMap, i.uv.zw + float2(0, _Time.y)).r;
                c += baseMap * 0.05f;
                float2 distortUV = lerp(screenUV, baseMap, (1 - baseMap) * _FlowDistort);
                //抓屏
                half4 opaqueTex = SAMPLE_TEXTURE2D(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, distortUV);
                half flow = frac(i.uv.y * _FlowTiling + _Time.y);
                c += opaqueTex * flow;
                //-----------------------

                return c;
            }
            ENDHLSL
        }
    }
}

1.近处高光

启用深度图

获取深度图,转到View空间下

片段着色器中:

此时我们获得了一个关于Cube的深度图

然后计算该顶点在View空间下的深度

顶点着色器中:

获取差距

添加细节半透明混合、约束范围并给出颜色

2.外发光

这个很简单,就是用菲涅尔

公式:pow(max(0, dot(N,V)), Intensity)

我们需要该顶点法线和该顶点指向相机的向量

顶点着色器:

然后带入公式

片段着色器:

因为我们需要的是外圈,所以需要1-NdotV,不然就是这样的

3.流动扭曲

流动的贴图

Y方向上的,被分割成几块的流动

使蜂窝贴图的缝隙偏移

1.计算偏移后的UV,使用1-baseMap是因为,黑色0需要偏移,白色1不需要偏移

2.抓屏

将抓屏结果和流动相乘,得到最终的流动扭曲结果

深度贴花

通过深度图求出像素所在的观察空间的Z值
通过当前渲染的面片求出像素在观察空间的坐标
将此坐标转换到本地空间,把XY当做UV进行采样

场景中使用Cube作为承载体,如果使用面片,在特定角度,图案会被切割

深度贴花
 Shader "MyURP/DepthDecal"
{
    Properties
    {
        _BaseColor("Base Color",color) = (1,1,1,1)
        _BaseMap("BaseMap", 2D) = "white" {}
    }
 
    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "RenderType" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderPipeline" = "UniversalPipeline"
        }
        LOD 100
        Blend One One
 
        Pass
        {
            Name "DepthDecal"

            HLSLPROGRAM

            // Required to compile gles 2.0 with standard srp library
            #pragma prefer_hlslcc gles
            #pragma exclude_renderers d3d11_9x
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
 
            struct Attributes
            {
                float4 positionOS       : POSITION;
            };
 
            struct Varyings
            {
                float4 positionCS       : SV_POSITION;
                float fogCoord          : TEXCOORD1;
                float3 positionVS       : TEXCOORD2;
            };
 
            CBUFFER_START(UnityPerMaterial)
            half4 _BaseColor;
            float4 _BaseMap_ST;
            CBUFFER_END
            TEXTURE2D (_BaseMap);SAMPLER(sampler_BaseMap);
            TEXTURE2D (_CameraDepthTexture);SAMPLER(sampler_CameraDepthTexture);
            #define smp _linear_clamp
            SAMPLER(smp);
 
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;

                float3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
                o.positionVS = TransformWorldToView(positionWS);
                o.positionCS = TransformWViewToHClip(o.positionVS);
                o.fogCoord = ComputeFogFactor(o.positionCS.z);
 
                return o;
            }
 
            half4 frag(Varyings i) : SV_Target
            {
                half4 c;

                float2 screenUV = i.positionCS.xy / _ScreenParams.xy;
                half depthMap = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, screenUV);
                //通过深度图求出像素所在的观察空间的Z值
                half depthZ = LinearEyeDepth(depthMap, _ZBufferParams);
                half4 depthVS = half4(0, 0, depthZ, 1);
                //通过当前渲染的面片求出像素在观察空间的XY坐标,使用的是相似三角形的比值,我们有了Z值
                //depthXY:depthZ = vsXY:vsZ
                depthVS.xy = i.positionVS.xy * depthZ / -i.positionVS.z;
                //将此观察空间坐标转换到本地空间,把XY当做UV进行采样
                half4 depthWS = mul(unity_CameraToWorld, depthVS);
                half3 depthOS = mul(unity_WorldToObject, depthWS);
                //采样
                half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, smp, depthOS.xz + 0.5);
                c = baseMap * _BaseColor;
                //雾效根据混合模式进行了调整
                c.rgb *= saturate(lerp(1, 0, i.fogCoord));

                return c;
            }
            ENDHLSL
        }
    }
}

定点消融效果

ASE/数组/简化ASE

案例的初心是简化ASE构造完成后的shader,但我感觉没意思,直接写吧,也不难

在世界空间下随机定几个点,让物体根据这些点产生如下图的效果

1.由C#脚本在Start时,将数组赋给shader

void Start()
{
    int n = transform.childCount;
    Vector4[] vectors = new Vector4[n];
    for (int i = 0; i < n; i++)
    {
        //遍历所有子物体,拿到所有子物体的pos,然后隐藏
        Transform child = transform.GetChild(i);
        vectors[i] = child.position;
        child.gameObject.SetActive(false);
    }
    Material mtl = GetComponent<MeshRenderer>().sharedMaterial;
    mtl.SetInt("StartPosCount", n);
    mtl.SetVectorArray("StartPosArr", vectors);
}

2.需要计算简单的Lambert光照,因此需要知道顶点法线

然后片段着色器就算一下

3.由于是在世界空间下计算的,因此顶点着色器需要计算顶点的世界坐标

然后片段着色器计算,具体解释都在代码中

GroundDisapper
 Shader "GroundDisapper"
{
	Properties
	{
		_Radius("Radius", Float) = 0
		_OutlineColor("OutlineColor", Color) = (0,0,0,0)
		_FadeRange("FadeRange", Float) = 0
		[Toggle(_DISAPPEAR_ON)]_Disappear("Disappear", Float) = 1
	}

	SubShader
	{
		Pass
		{
			Name "FORWARD"
			Tags { "LightMode" = "ForwardBase" }

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0
			#pragma multi_compile _ _DISAPPEAR_ON
			#include "UnityCG.cginc"

			struct Input
			{
				float3 worldNormal;
				float3 worldPos;
			};

			int StartPosCount;
			float4 StartPosArr[5];
			float _Radius;
			float _FadeRange;
			float4 _OutlineColor;

			struct appdata
			{
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
			};

			v2f vert (appdata v)
			{
				v2f o;

				o.pos = UnityObjectToClipPos(v.vertex);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
			
				return o;
			}

			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 c = 0;

				//Lambert lighting
				fixed4 NdotL = dot(i.worldNormal, _WorldSpaceLightPos0.xyz);
				fixed4 diffuse = (NdotL * 0.5 + 0.5) * 0.4;

				#ifdef _DISAPPEAR_ON
					//获取渐变内侧终点
					float fadeMin = _Radius - _FadeRange;
					//获取渐变外侧起点,同时也是半径
					float fadeMax = _Radius;
					//起始假设该点在半径之外,倘若最后真的在半径之外,会被clip(0.999-1)剔除
					float outline = 1;
					//遍历所有的圆心,只要有一个小于1,最后就能被保留
					for (uint idx = 0; idx < StartPosCount; idx++)
					{
						float3 startPos = StartPosArr[idx].xyz;
						//saturate(该点离内侧的距离 / 外侧离内侧的距离)
						float fade = saturate((distance(i.worldPos, startPos) - fadeMin) / (fadeMax - fadeMin));
						outline *= fade;
					}
					clip(0.999 - outline);
					c = outline * _OutlineColor + diffuse;
				#else
					c = diffuse;
				#endif
			
				return c;
			}

			ENDCG
		}
	}
}

裂痕深坑

此处为渲染顺序和色彩模板的配合知识点

渲染裂痕下部分,写入深度,写入颜色值

渲染裂痕上部分,写入深度覆盖渲染裂痕下部分的深度,不写入颜色值

渲染地面,写入深度,发现部分片段不如裂痕上部分浅,取消这部分片段的渲染

场景部分:

其中up就是down模型的压缩版,Scale.y = 0

下部分Shader:

重要的就是"Queue"="Geometry-2",显示的东西就是模型,Cull Front无所谓,建模时不小心法线反了,懒得改了

down
 Shader "MyURP/CrackDown"
{
    Properties
    {
        _BaseColor("Base Color",color) = (1,1,1,1)
    }
 
    SubShader
    {
        Tags
        {
            "Queue"="Geometry-2"
            "RenderType" = "Opaque"
            "IgnoreProjector" = "True"
            "RenderPipeline" = "UniversalPipeline"
        }
        LOD 100
 
        Pass
        {
            Name "CrackDown"
            Cull Front

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
 
            struct Attributes
            {
                float4 positionOS       : POSITION;
            };
 
            struct Varyings
            {
                float4 positionCS       : SV_POSITION;
                float3 positionOS       : TEXCOORD0;
                float fogCoord          : TEXCOORD1;
            };
 
            CBUFFER_START(UnityPerMaterial)
            half4 _BaseColor;
            CBUFFER_END
 
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;
 
                o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
                o.positionOS = v.positionOS.xyz;
                o.fogCoord = ComputeFogFactor(o.positionCS.z);
 
                return o;
            }
 
            half4 frag(Varyings i) : SV_Target
            {
                half4 c = 1;

                half mask = abs(i.positionOS.y);
                float t = sin(_Time.y);
                t = t * 0.3 + 0.7;
                c.rgb = lerp(0, _BaseColor * t, mask);

                return c;
            }
            ENDHLSL
        }
    }
}

上部分Shader:

重要的部分就是"Queue"="Geometry-1"、ColorMask 0

up
 Shader "MyURP/CrackUP"
{
    SubShader
    {
        Tags
        {
            "Queue"="Geometry-1"
            "RenderType" = "Opaque"
            "IgnoreProjector" = "True"
            "RenderPipeline" = "UniversalPipeline"
        }
        LOD 100
 
        Pass
        {
            Name "CrackUP"
            Cull Front
            ColorMask 0

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
 
            struct Attributes
            {
                float4 positionOS       : POSITION;
            };
 
            struct Varyings
            {
                float4 positionCS       : SV_POSITION;
            };
 
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;
 
                o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
 
                return o;
            }
 
            half4 frag(Varyings i) : SV_Target
            {
                return 0;
            }
            ENDHLSL
        }
    }
}

最后渲染的就是一般的不透明物体,队列为Geometry,在up之后

但在渲染时发现自己太深,通不过深度测试,于是显示的就是首次渲染的down

posted @ 2024-05-15 16:33  被迫吃冰淇淋的小学生  阅读(331)  评论(0)    收藏  举报