美文网首页
Deferred路径中的StandardShader

Deferred路径中的StandardShader

作者: 万里_aa3f | 来源:发表于2019-03-11 00:45 被阅读0次

    前向渲染对每个物体每个光源都需要一个额外的附加渲染通道,这使得如果灯光变多draw call会急剧的增加。
    在每次前向渲染的过程中,我们都要转换模型数据,再进行fragmentshader求出光照。这么麻烦,我们为什么不将几何数据缓存起来。而这对于多个光源的场景来书会节省很多draw call

    1.延迟路径第一步:填充几何缓冲区

    struct FragmentOutput{
        float4 gBuffer0:SV_TARGET0;
        float4 gBuffer1:SV_TARGET1;
        float4 gBuffer2:SV_TARGET2;
        float4 gBuffer3:SV_TARGET3;
    };
    
    1.缓冲区0

    第一个G缓冲区用于存储漫反射率和表面遮挡。这是一个ARGB32纹理,就像一个常规的帧缓冲区。反射率存储在RGB通道中,遮挡存储在A通道中。

    finalOutput.gBuffer0.xyz=albedo;
        finalOutput.gBuffer0.a=GetAO(i);
    
    2.缓冲区1

    第二个G缓冲器用于存储RGB通道中的镜面高光颜色,以及A通道中的平滑度值。它也是一个ARGB32纹理。

    finalOutput.gBuffer1.xyz=specular;
    finalOutput.gBuffer1.a=smoothness;
    
    3.缓冲区2

    第三个G缓冲区包含的是世界空间中的法向量。它们存储在ARGB2101010纹理的RGB通道中。
    因为我们输出的值域为0-1,而世界坐标中法线方向的向量范围是-1,1。对此应做映射

    finalOutput.gBuffer2=float4(normal*0.5+0.5,1.0);
    
    4.缓冲区3

    用于存储积累的光照,格式分为两种一种是储存低动态对比度的ARGB2101010,另一种存高动态对比度颜色ARGBHalf;
    对于积累的光照,在写入GBuffer时,应加入SH球谐环境光、和自发光;
    也可以加入反射,或者是在延迟光照的方法考虑进去
    当关闭HDR时,要将光照进行编码

    #pragma multi_compile _ UNITY_HDR_ON
    #if !defined(UNITY_HDR_ON)
            finalCol=exp2(-finalCol);
    #endif
    finalOutput.gBuffer3=float4(finalCol,1.0);
    

    GBuffer-shader

    Shader"myshader/DeferredMat"{
        Properties{
            _mainTex("MainTex",2D)="white"{}
            _Tine("Time",Color)=(1,1,1,1)
            [NoScaleOffset]_MetallicMap("MetallicMap",2D)="black"{}
            _Metallic("Metallic",Range(0,1))=0
            _Smoothness("smoothness",Range(0,1))=0
    
            [NoScaleOffset]_NormalMap("NormalMap",2D)="Bump"{}
            _NormalScale("NormalScale",float)=1
    
            _AoScale("AoScale",Range(0,1))=1
            [NoScaleOffset]_EmissionMap("EmissionMap",2D)="black"
    
        }
    
        SubShader{
            Tags{"RenderType"="Opaque"}
    
    
            pass{
                Tags{"LightMode"="Deferred"}
                CGPROGRAM
    
                #pragma target 3.0
                #pragma vertex vert 
                #pragma fragment frag 
                #pragma multi_compile _ UNITY_HDR_ON
    
                #include"WriteInGBuffer.cginc"
    
                ENDCG
            }
    
    
        }
        Fallback "Diffuse"
    }
    
    
    #if !defined(MY_LIGHTING_INCLUDED)
    #define MY_LIGHTING_INCLUDED
    
    #include"UnityPBSLighting.cginc"
    #include"AutoLight.cginc"
    #include"UnityStandardUtils.cginc"
    
    sampler2D _mainTex;
    float4 _mainTex_ST;
    float3 _Tine;
    
    sampler2D _MetallicMap;
    float _Metallic;
    float _Smoothness;
    
    sampler2D _NormalMap;
    float _NormalScale;
    
    float _AoScale;
    sampler2D _EmissionMap;
    
    struct a2v{
        float4 vertex:POSITION;
        float3 normal:NORMAL;
        float2 uv:TEXCOORD;
        float4 tangent:TANGENT;
    };
    
    struct v2f{
        float4 pos:SV_POSITION;
        float3 worldPos:TEXCOORD0;
        float3 normal:TEXCOORD1;
        float4 tangent:TEXCOORD2;
        float2 uv:TEXCOORD3;
    
    };
    
    
    
    v2f vert(a2v v){
        v2f o;
        o.pos=UnityObjectToClipPos(v.vertex);
        o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
        o.normal=UnityObjectToWorldNormal(v.normal);
        o.tangent=float4(UnityObjectToWorldDir(v.tangent.xyz),v.tangent.w);
        o.uv=TRANSFORM_TEX(v.uv,_mainTex);
        return o;
    }
    
    float3 GetAlbedo(v2f i){
        return tex2D(_mainTex,i.uv).xyz * _Tine.xyz;
    }
    
    float GetMetallic(v2f i){
        return tex2D(_MetallicMap,i.uv).r + _Metallic;
    }
    
    float GetSmoothness(v2f i){
        return _Smoothness;
    }
    
    float3 GetNormal(v2f i){
        float3 worldNormal=normalize(i.normal);
        float3 worldTangent=normalize(i.tangent.xyz);
        float3 worldBinormal=cross(worldNormal,worldTangent) * i.tangent.w * unity_WorldTransformParams.w;
    
        float3 tangentNormal=UnpackScaleNormal(tex2D(_NormalMap,i.uv),_NormalScale);
        return float3(
            tangentNormal.x*worldTangent+
            tangentNormal.y*worldBinormal+
            tangentNormal.z*worldNormal
        );
    }
    
    float GetAO(v2f i){
        return 1.;
    }
    
    UnityLight GetdirLight(v2f i){
        UnityLight dirLight;
        dirLight.dir=UnityWorldSpaceLightDir(i.worldPos);
    
        UNITY_LIGHT_ATTENUATION(attenuation,i,i.worldPos);
        dirLight.color=_LightColor0.xyz * attenuation;
        return dirLight;
    }
    
    UnityIndirect GetindirLight(v2f i,float3 viewDir){
        UnityIndirect indirLight;
        indirLight.diffuse=0;
        indirLight.specular=0;
    
        indirLight.diffuse-=max(0,ShadeSH9(float4(i.normal,1)));
    
        Unity_GlossyEnvironmentData envData;
        envData.roughness = 1 - GetSmoothness(i);
        float3 reflectDir=reflect(-viewDir,i.normal);
    
        float3 reflectDir1=BoxProjectedCubemapDirection(reflectDir, i.worldPos,unity_SpecCube0_ProbePosition,unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
        envData.reflUVW = reflectDir1;
        float3 probe0 = Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, envData);
    
        float3 reflectDir2=BoxProjectedCubemapDirection(reflectDir, i.worldPos,unity_SpecCube1_ProbePosition,unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
        envData.reflUVW = reflectDir2;
        float3 probe1= Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1, unity_SpecCube0),unity_SpecCube0_HDR, envData);
        indirLight.specular = lerp(probe1, probe0, unity_SpecCube0_BoxMin.w);
    
        float AO = GetAO(i);
        indirLight.diffuse*=AO;
        indirLight.specular*=AO;
    
        #if defined(UNITY_ENABLE_REFLECTION_BUFFERS)
            indirLight.specular=0;
        #endif
    
        
        return indirLight;
    }
    
    float3 GetEmission(v2f i){
        float3 emission=tex2D(_EmissionMap,i.uv).xyz;
        return emission;
    }
    
    struct FragmentOutput{
        float4 gBuffer0:SV_TARGET0;
        float4 gBuffer1:SV_TARGET1;
        float4 gBuffer2:SV_TARGET2;
        float4 gBuffer3:SV_TARGET3;
    };
    
    FragmentOutput frag(v2f i){
        float3 albedo=GetAlbedo(i);
    
        float metallic=GetMetallic(i);
        float3 specular;
        float OneMinuseReflectivity;
        albedo = DiffuseAndSpecularFromMetallic(albedo,metallic,specular,OneMinuseReflectivity);
    
        float smoothness=GetSmoothness(i);
        float3 normal=GetNormal(i);
        float3 viewDir=normalize(UnityWorldSpaceViewDir(i.worldPos));
    
        UnityLight dirLight;            //将直接光照设置为0,
        dirLight.dir=float3(0,1,0);
        dirLight.color=float3(0,0,0);
        UnityIndirect indirLight=GetindirLight(i,viewDir);
    
        fixed3 BRDF=UNITY_BRDF_PBS(albedo,specular,OneMinuseReflectivity,smoothness,normal,viewDir,dirLight,indirLight);
        fixed3 emissionCol=GetEmission(i);
        fixed3 finalCol=BRDF+emissionCol;
    
        #if !defined(UNITY_HDR_ON)
            finalCol=exp2(-finalCol);
        #endif
        
        FragmentOutput finalOutput;
        finalOutput.gBuffer0.xyz=albedo;
        finalOutput.gBuffer0.a=GetAO(i);
        finalOutput.gBuffer1.xyz=specular;
        finalOutput.gBuffer1.a=smoothness;
        finalOutput.gBuffer2=float4(normal*0.5+0.5,1.0);
        finalOutput.gBuffer3=float4(finalCol,1.0);
    
        return finalOutput;
    }
    
    #endif
    

    二、延迟光照

    目前我们已经得到4个缓冲区,现在我们利用这些缓冲区在lightingshader中计算灯光

    1.deferredLighting中的两个Pass

    第一个pass中用来计算光照,第二个pass是,当关闭HDR时,才会被调用,用来将HDR转换为LDR

    SubShader{
            pass{
                Blend [_SrcBlend] [_DstBlend]
                Cull Off
                ZTest Always
                ZWrite Off
    
                CGPROGRAM
                #pragma target 3.0
                #pragma vertex vert 
                #pragma fragment frag 
                #pragma exclude_renderers nomrt
                #pragma multi_compile_lightpass
                #pragma multi_compile _ UNITY_HDR_ON
                
                #include "DeferredLighting.cginc"
    
    
                ENDCG
            }
    
            pass{
                Cull off 
                ZTest Always 
                ZWrite off 
                //用蒙版缓冲区消除对背景的影响
                Stencil{
                    Ref [_StencilNonBackground]
                    ReadMask [_StencilNonBackground]
                    CompBack Equal
                    CompFront Equal
                }
    
                CGPROGRAM
                #pragma target 3.0
                #pragma vertex vert 
                #pragma fragment frag 
                #pragma exclude_renderers nomrt
                #include"UnityCG.cginc"
    
                struct a2v{
                    float4 vertex:POSITION;
                    float2 uv:TEXCOORD0;
                };
                struct v2f{
                    float4 pos:SV_POSITION;
                    float2 uv:TEXCOORD0;
                };
    
                sampler2D _LightBuffer;
    
    
                v2f vert(a2v v){
                    v2f o;
                    o.uv=v.uv;
                    o.pos=UnityObjectToClipPos(v.vertex);
                    return o;
                }
    
    
                float4 frag(v2f i):SV_TARGET{
                    return -log2(tex2D(_LightBuffer,i.uv));
                }
                ENDCG
            }
        }
    

    灯光计算(第一个pass)

    1.读取G缓冲区的uv坐标

        i.pos = UnityObjectToClipPos(v.vertex);
        i.uv = ComputeScreenPos(i.pos);
        float2 uv = i.uv.xy / i.uv.w;
    

    2.世界坐标

    normal的法线信息是沿着视角射线的方向的

    UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
    
    i.ray = v.normal;
    
    float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
    depth = Linear01Depth(depth);
    float3 rayToFarPlane = i.ray * _ProjectionParams.z / i.ray.z;
    float3 viewPos = rayToFarPlane * depth;
    float3 worldPos = mul(unity_CameraToWorld, float4(viewPos, 1)).xyz;
    

    3.读取G缓冲数据

    sampler2D _CameraGBufferTexture0;
    sampler2D _CameraGBufferTexture1;
    sampler2D _CameraGBufferTexture2;
    
    float3 worldPos = mul(unity_CameraToWorld, float4(viewPos, 1)).xyz;
    float3 albedo = tex2D(_CameraGBufferTexture0, uv).rgb;
    float3 specularTint = tex2D(_CameraGBufferTexture1, uv).rgb;
    float3 smoothness = tex2D(_CameraGBufferTexture1, uv).a;
    float3 normal = tex2D(_CameraGBufferTexture2, uv).rgb * 2 - 1;
    

    4.计算BRDF

    float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
    float3 albedo = tex2D(_CameraGBufferTexture0, uv).rgb;
    float3 specularTint = tex2D(_CameraGBufferTexture1, uv).rgb;
    float3 smoothness = tex2D(_CameraGBufferTexture1, uv).a;
    float3 normal = tex2D(_CameraGBufferTexture2, uv).rgb * 2 - 1;
    float oneMinusReflectivity = 1 - SpecularStrength(specularTint);
    UnityLight light;
    light.color = 0;
    light.dir = 0;
    UnityIndirect indirectLight;
    indirectLight.diffuse = 0;
    indirectLight.specular = 0;
    float4 color = UNITY_BRDF_PBS(albedo, specularTint, oneMinusReflectivity, smoothness,normal, viewDir, light, indirectLight);
    

    5.平行光灯光参数

    间接灯光在写入GBuffer中时已经加入了,所以indirLight继续填0
    灯光方向和颜色是从float4 _LightColor, _LightDir 中读取,注意LightDir为灯光前进方向,应取反

    float4 _LightColor, _LightDir;
    UnityLight CreateLight () {
        UnityLight light;
        light.dir =- _LightDir;
        light.color = _LightColor.rgb;
        return light;
    }
    

    6.平行光阴影+COOKIE

    1.依靠AutoLight的宏来确定由阴影引起的光衰减。 不幸的是,该文件没有写入延迟光源。 所以我们自己来进行阴影采样。阴影贴图可以通过_ShadowMapTexture变量来访问。但是,我们不能随便声明这个变量。 它已经为UnityShadowLibrary中被定义点光源和聚光光源的阴影,我们间接导入了它们。 所以我们不应该自己定义它,除非使用方向光源的阴影。
    2.UnityComputeShadowFadeDistance(worldPos, viewZ) 计算阴影衰减
    UnityComputeShadowFade 计算衰减距离

    #if defined (SHADOWS_SCREEN)
        sampler2D _ShadowMapTexture;
    #endif
    
        float attenuation = 1;
        float shadowAttenuation =1.0;
        #if defined(DIRECTIONAL) || defined(DIRECTIONAL_COOKIE)
            #if defined(DIRECTIONAL_COOKIE)
                float2 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1)).xy;
                attenuation *= tex2Dbias(_LightTexture0, float4(uvCookie, 0, -8)).w;
                //attenuation *= tex2D(_LightTexture0, uvCookie).w;
            #endif
    
            #if defined (SHADOWS_SCREEN)
                shadowAttenuation = tex2D(_ShadowMapTexture, uv).r;
                float shadowFadeDistance = UnityComputeShadowFadeDistance(worldPos, viewZ);
                float shadowFade = UnityComputeShadowFade(shadowFadeDistance);
                shadowAttenuation = saturate(shadowAttenuation + shadowFade);
            #endif
        #else
            light.dir = 1;
        #endif
    
        light.color = _LightColor.rgb * shadowAttenuation * attenuation;
    

    不要忘记LDR的编码,像GBuffer写入时 一样

    #if !defined(UNITY_HDR_ON)
        color = exp2(-color);
    #endif
    

    7.加入聚光灯

    1.金字塔区域被渲染为一个常规的3D对象。

    摄像机可能会在聚光光源照亮的体积的内部。 甚至可能近平面的一部分都在聚光光源照亮的体积的内部,而其余部分位于聚光光源照亮的体积的外部。在这些情况下,模板缓冲区不能用于限制渲染。

    Blend [_SrcBlend] [_DstBlend]
    //Cull Off
    //ZTest Always
    ZWrite Off
    
    2.计算光源方向
    float4 _LightColor, _LightDir, _LightPos;
    float3 lightVec = _LightPos.xyz - worldPos;
    light.dir = normalize(lightVec);
    
    3.再次计算世界坐标

    当时平行光的时候,_LightAsQuad=1

    float _LightAsQuad;
    i.ray = lerp(UnityObjectToViewPos(v.vertex) * float3(-1, -1, 1),v.normal,_LightAsQuad);
    
    4.Cookie衰减

    _LightTexture0存入Cookie的数值

    float4 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1));
    uvCookie.xy /= uvCookie.w;
    attenuation *= tex2Dbias(_LightTexture0, float4(uvCookie.xy, 0, -8)).w;
    attenuation *= uvCookie.w < 0;
    
    5.距离衰减

    聚光光源的光线也会根据距离进行衰减。该衰减存储在查找纹理中,可通过_LightTextureB0获得。
    光源的范围存储在_LightPos的第四个变量中。
    使用哪个纹理通道,因平台而异,由UNITY_ATTEN_CHANNEL宏进行定义。

    sampler2D _LightTexture0, _LightTextureB0;
    attenuation *= tex2D(_LightTextureB0,(dot(lightVec, lightVec) * _LightPos.w).rr).UNITY_ATTEN_CHANNEL;
    
    6.阴影

    当聚光光源有阴影的时候,会定义SHADOWS_DEPTH关键字。

    #if defined(SHADOWS_DEPTH)
        shadowed = true;
    #endif
    shadowAttenuation = UnitySampleShadowmap(mul(unity_WorldToShadow[0], float4(worldPos, 1)));
    

    8.点光源

    与聚光灯原理类似
    完整的光源衰减

    UnityLight CreateLight (float2 uv, float3 worldPos, float viewZ) {
        UnityLight light;
        float attenuation = 1;
        float shadowAttenuation = 1;
        bool shadowed = false;
    
        #if defined(DIRECTIONAL) || defined(DIRECTIONAL_COOKIE)
            light.dir = -_LightDir;
    
            #if defined(DIRECTIONAL_COOKIE)
                float2 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1)).xy;
                attenuation *= tex2Dbias(_LightTexture0, float4(uvCookie, 0, -8)).w;
            #endif
    
            #if defined(SHADOWS_SCREEN)
                shadowed = true;
                shadowAttenuation = tex2D(_ShadowMapTexture, uv).r;
            #endif
        #else
            float3 lightVec = _LightPos.xyz - worldPos;
            light.dir = normalize(lightVec);
    
            attenuation *= tex2D(
                _LightTextureB0,
                (dot(lightVec, lightVec) * _LightPos.w).rr
            ).UNITY_ATTEN_CHANNEL;
    
            #if defined(SPOT)
                float4 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1));
                uvCookie.xy /= uvCookie.w;
                attenuation *=
                    tex2Dbias(_LightTexture0, float4(uvCookie.xy, 0, -8)).w;
                attenuation *= uvCookie.w < 0;
    
                #if defined(SHADOWS_DEPTH)
                    shadowed = true;
                    shadowAttenuation = UnitySampleShadowmap(
                        mul(unity_WorldToShadow[0], float4(worldPos, 1))
                    );
                #endif
            #else
                #if defined(POINT_COOKIE)
                    float3 uvCookie =
                        mul(unity_WorldToLight, float4(worldPos, 1)).xyz;
                    attenuation *=
                        texCUBEbias(_LightTexture0, float4(uvCookie, -8)).w;
                #endif
                
                #if defined(SHADOWS_CUBE)
                    shadowed = true;
                    shadowAttenuation = UnitySampleShadowmap(-lightVec);
                #endif
            #endif
        #endif
    
        if (shadowed) {
            float shadowFadeDistance =
                UnityComputeShadowFadeDistance(worldPos, viewZ);
            float shadowFade = UnityComputeShadowFade(shadowFadeDistance);
            shadowAttenuation = saturate(shadowAttenuation + shadowFade);
    
            #if defined(UNITY_FAST_COHERENT_DYNAMIC_BRANCHING) && defined(SHADOWS_SOFT)
                UNITY_BRANCH
                if (shadowFade > 0.99) {
                    shadowAttenuation = 1;
                }
            #endif
        }
    
        light.color = _LightColor.rgb * (attenuation * shadowAttenuation);
        return light;
    }
    
    

    完整光照计算Shader

    Shader "Custom/DeferredShading" {
        
        Properties {
        }
    
        SubShader {
    
            Pass {
                Blend [_SrcBlend] [_DstBlend]
                ZWrite Off
    
                CGPROGRAM
    
                #pragma target 3.0
                #pragma vertex VertexProgram
                #pragma fragment FragmentProgram
    
                #pragma exclude_renderers nomrt
    
                #pragma multi_compile_lightpass
                #pragma multi_compile _ UNITY_HDR_ON
    
                #include "MyDeferredShading.cginc"
    
                ENDCG
            }
    
            Pass {
                Cull Off
                ZTest Always
                ZWrite Off
    
                Stencil {
                    Ref [_StencilNonBackground]
                    ReadMask [_StencilNonBackground]
                    CompBack Equal
                    CompFront Equal
                }
    
                CGPROGRAM
    
                #pragma target 3.0
                #pragma vertex VertexProgram
                #pragma fragment FragmentProgram
    
                #pragma exclude_renderers nomrt
    
                #include "UnityCG.cginc"
    
                sampler2D _LightBuffer;
    
                struct VertexData {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct Interpolators {
                    float4 pos : SV_POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                Interpolators VertexProgram (VertexData v) {
                    Interpolators i;
                    i.pos = UnityObjectToClipPos(v.vertex);
                    i.uv = v.uv;
                    return i;
                }
    
                float4 FragmentProgram (Interpolators i) : SV_Target {
                    return -log2(tex2D(_LightBuffer, i.uv));
                }
    
                ENDCG
            }
        }
    }
    
    #if !defined(MY_DEFERRED_SHADING)
    #define MY_DEFERRED_SHADING
    
    #include "UnityPBSLighting.cginc"
    
    UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
    
    sampler2D _CameraGBufferTexture0;
    sampler2D _CameraGBufferTexture1;
    sampler2D _CameraGBufferTexture2;
    
    #if defined(POINT_COOKIE)
        samplerCUBE _LightTexture0;
    #else
        sampler2D _LightTexture0;
    #endif
    
    sampler2D _LightTextureB0;
    float4x4 unity_WorldToLight;
    
    #if defined (SHADOWS_SCREEN)
        sampler2D _ShadowMapTexture;
    #endif
    
    float4 _LightColor, _LightDir, _LightPos;
    
    float _LightAsQuad;
    
    struct VertexData {
        float4 vertex : POSITION;
        float3 normal : NORMAL;
    };
    
    struct Interpolators {
        float4 pos : SV_POSITION;
        float4 uv : TEXCOORD0;
        float3 ray : TEXCOORD1;
    };
    
    UnityLight CreateLight (float2 uv, float3 worldPos, float viewZ) {
        UnityLight light;
        float attenuation = 1;
        float shadowAttenuation = 1;
        bool shadowed = false;
    
        #if defined(DIRECTIONAL) || defined(DIRECTIONAL_COOKIE)
            light.dir = -_LightDir;
    
            #if defined(DIRECTIONAL_COOKIE)
                float2 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1)).xy;
                attenuation *= tex2Dbias(_LightTexture0, float4(uvCookie, 0, -8)).w;
            #endif
    
            #if defined(SHADOWS_SCREEN)
                shadowed = true;
                shadowAttenuation = tex2D(_ShadowMapTexture, uv).r;
            #endif
        #else
            float3 lightVec = _LightPos.xyz - worldPos;
            light.dir = normalize(lightVec);
    
            attenuation *= tex2D(
                _LightTextureB0,
                (dot(lightVec, lightVec) * _LightPos.w).rr
            ).UNITY_ATTEN_CHANNEL;
    
            #if defined(SPOT)
                float4 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1));
                uvCookie.xy /= uvCookie.w;
                attenuation *=
                    tex2Dbias(_LightTexture0, float4(uvCookie.xy, 0, -8)).w;
                attenuation *= uvCookie.w < 0;
    
                #if defined(SHADOWS_DEPTH)
                    shadowed = true;
                    shadowAttenuation = UnitySampleShadowmap(
                        mul(unity_WorldToShadow[0], float4(worldPos, 1))
                    );
                #endif
            #else
                #if defined(POINT_COOKIE)
                    float3 uvCookie =
                        mul(unity_WorldToLight, float4(worldPos, 1)).xyz;
                    attenuation *=
                        texCUBEbias(_LightTexture0, float4(uvCookie, -8)).w;
                #endif
                
                #if defined(SHADOWS_CUBE)
                    shadowed = true;
                    shadowAttenuation = UnitySampleShadowmap(-lightVec);
                #endif
            #endif
        #endif
    
        if (shadowed) {
            float shadowFadeDistance =
                UnityComputeShadowFadeDistance(worldPos, viewZ);
            float shadowFade = UnityComputeShadowFade(shadowFadeDistance);
            shadowAttenuation = saturate(shadowAttenuation + shadowFade);
    
            #if defined(UNITY_FAST_COHERENT_DYNAMIC_BRANCHING) && defined(SHADOWS_SOFT)
                UNITY_BRANCH
                if (shadowFade > 0.99) {
                    shadowAttenuation = 1;
                }
            #endif
        }
    
        light.color = _LightColor.rgb * (attenuation * shadowAttenuation);
        return light;
    }
    
    Interpolators VertexProgram (VertexData v) {
        Interpolators i;
        i.pos = UnityObjectToClipPos(v.vertex);
        i.uv = ComputeScreenPos(i.pos);
        i.ray = lerp(
            UnityObjectToViewPos(v.vertex) * float3(-1, -1, 1),
            v.normal,
            _LightAsQuad
        );
        return i;
    }
    
    float4 FragmentProgram (Interpolators i) : SV_Target {
        float2 uv = i.uv.xy / i.uv.w;
    
        float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
        depth = Linear01Depth(depth);
    
        float3 rayToFarPlane = i.ray * _ProjectionParams.z / i.ray.z;
        float3 viewPos = rayToFarPlane * depth;
        float3 worldPos = mul(unity_CameraToWorld, float4(viewPos, 1)).xyz;
        float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
    
        float3 albedo = tex2D(_CameraGBufferTexture0, uv).rgb;
        float3 specularTint = tex2D(_CameraGBufferTexture1, uv).rgb;
        float3 smoothness = tex2D(_CameraGBufferTexture1, uv).a;
        float3 normal = tex2D(_CameraGBufferTexture2, uv).rgb * 2 - 1;
        float oneMinusReflectivity = 1 - SpecularStrength(specularTint);
    
        UnityLight light = CreateLight(uv, worldPos, viewPos.z);
        UnityIndirect indirectLight;
        indirectLight.diffuse = 0;
        indirectLight.specular = 0;
    
        float4 color = UNITY_BRDF_PBS(
            albedo, specularTint, oneMinusReflectivity, smoothness,
            normal, viewDir, light, indirectLight
        );
        #if !defined(UNITY_HDR_ON)
            color = exp2(-color);
        #endif
        return color;
    }
    
    #endif
    

    相关文章

      网友评论

          本文标题:Deferred路径中的StandardShader

          本文链接:https://www.haomeiwen.com/subject/qhympqtx.html