找回密码
 立即注册
查看: 305|回复: 0

【Free Bird/URP教学】9.浅谈unity的depth写入问题(bulid …

[复制链接]
发表于 2022-4-29 17:26 | 显示全部楼层 |阅读模式
顺便做了视频
【URP】
在URP中的深度写入主要通过DepthOnly的name pass来进行深度写入,具体例子为如下代码所示
Shader "lit/Phong模型"//shader名字

{
    Properties
    {
        _MainTex ("主贴图", 2D) = "white" { }//汇入数据的位置
        _NormalTex ("法线贴图", 2D) = "bump" { }//汇入法线
        _NormalTexScale ("法线强度", float) = 1.0//汇入法线强度
        _GlossScale ("高光放缩", range(0.0, 50.0)) = 1.0
    }
    SubShader
    {
        //定义不透明物体,用的是URP管线,定义队列是不透明队列
        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "Queue" = "Geometry" }
        LOD 100

        Pass
        {
            HLSLPROGRAM

            //定义hlsl语言

            //定义顶点着色器的名字
            #pragma vertex vert
            //定义片元着色器的名字
            #pragma fragment frag
            //汇入函数库以及汇入光照的hlsl
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"//函数库:主要用于各种的空间变换
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"//从unity中取得我们的光照

            //汇入模型的数据
            struct appdata
            {
                float4 vertex : POSITION;//汇入模型的顶点
                float3 normal : NORMAL;//汇入法线
                float2 uv : TEXCOORD0;//汇入uv
                float4 tangent : TANGENT;//汇入切线

            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float3 normal_world : TEXCOORD1;//世界空间的法线
                float3 tangent_world : TEXCOORD2;//世界空间的切线
                float3 bitangent_world : TEXCOORD3;//世界空间的次切线
                float3 vertex_world : TEXCOORD4;//顶点的世界空间
                float4 vertex : SV_POSITION;
            };

            TEXTURE2D(_MainTex);SAMPLER(sampler_MainTex);float4 _MainTex_ST;//采样贴图,采样前面汇入的maintex贴图,贴图采样器,以及贴图st
            TEXTURE2D(_NormalTex);SAMPLER(sampler_NormalTex);//采样贴图,采样前面汇入的法线贴图,贴图采样器,以及贴图st
            float _NormalTexScale, _GlossScale;//汇入法线scale

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = TransformObjectToHClip(v.vertex);//模型空间转换到裁剪空间
                o.vertex_world = TransformObjectToWorld(v.vertex.xyz);//顶点世界空间
                o.normal_world = TransformObjectToWorldNormal(v.normal);//法线从模型空间转换到世界空间
                o.tangent_world = TransformObjectToWorldDir(v.tangent);//切线变换
                o.bitangent_world = normalize(cross(o.normal_world, o.tangent_world)) * v.tangent.w * unity_WorldTransformParams.w;//次切线
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);//UV由主贴图进行定义
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {
                // 【主贴图采样】
                float4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);//主贴图采样
                float4 pack_normal = SAMPLE_TEXTURE2D(_NormalTex, sampler_NormalTex, i.uv);//法线采样
                float3 unpack_normal = UnpackNormal(pack_normal);//得到法线具体数据

                //法线图的修正
                unpack_normal.xy *= _NormalTexScale;
                unpack_normal.z = 1.0 - saturate(dot(unpack_normal.xy, unpack_normal.xy));

                //【光照与各种向量】
                Light light = GetMainLight();//获取主光源
                float3 L = light.direction;//获取光照方向
                float3 N = normalize(unpack_normal.x * i.tangent_world + unpack_normal.y * i.bitangent_world + unpack_normal.z * i.normal_world);//法线
                float3 V = normalize(_WorldSpaceCameraPos - i.vertex_world);//视角方向
                float3 H = normalize(L + V);//半程向量

                //【计算漫反射】
                float diffuse_Term = max(dot(L, N), 0.0);//定义漫反射项
                float3 diffuse = light.color.rgb * diffuse_Term * col.rgb;//光照颜色*漫反射*物体颜色
                //【计算高光反射】
                float NoH = max(0.0, dot(N, H));//高光noh
                float3 specular = light.color.rgb * col.rgb * pow(NoH, _GlossScale);//高光项

                return float4(diffuse + specular, 1.0);
            }
            ENDHLSL

        }
        //【pass:深度】
        Pass
        {
            Name "DepthOnly"
            Tags{"LightMode" = "DepthOnly"}

            ZWrite On
            ColorMask 0
            Cull off

            HLSLPROGRAM
            // Required to compile gles 2.0 with standard srp library

            #pragma vertex DepthOnlyVertex
            #pragma fragment DepthOnlyFragment

            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
            ENDHLSL
        }
    }
}
通过depthonly的pass,我们便可以完成深度的写入:



加入depthonly的pass效果

其实也很简单的原理,主要加入裁剪与透明度判断的代码:



采样透明度函数



采样基础贴图的Alpha

【Bulid-in】
在bulid-in里面,我们需要写入shadowcaster来进行深度写入,当我们的shader没有shadowcaster,深度不会写入:



无shadowcaster



有shadowcaster

Shader "Unlit/NewUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" { }
    }
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100

        Pass
        {
            Cull Off
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            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);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG

        }
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }
            Cull Off
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_shadowcaster
            #pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders
            #include "UnityCG.cginc"

            struct v2f
            {
                V2F_SHADOW_CASTER;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            v2f vert(appdata_base v)
            {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {
                SHADOW_CASTER_FRAGMENT(i)
            }
            ENDCG

        }
    }
}
当然记得shadowcaster看情况,如果你的物件不要背面剔除,那么shadowcaster也不能要背面剔除:



shadowcaster背面剔除但是主渲染没有剔除的结果

【build-in源代码】
链接:https://pan.baidu.com/s/1NCaSo9uoVpFBn3fYhO3PqQ
提取码:fbfb
【URP源代码】
主要在这个shader,其余文件为本人的URP课程文件:Assets\Phong.shader
链接:https://pan.baidu.com/s/1A4Km1GgPkaat7ICJCS-Osw
提取码:fbfb

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 13:45 , Processed in 0.066559 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表