standard pbr(三)-BRDF

// Default BRDF to use:
#if !defined (UNITY_BRDF_PBS) // allow to explicitly override BRDF in custom shader
    // still add safe net for low shader models, otherwise we might end up with shaders failing to compile
    #if SHADER_TARGET < 30
        #define UNITY_BRDF_PBS BRDF3_Unity_PBS
    #elif UNITY_PBS_USE_BRDF3
        #define UNITY_BRDF_PBS BRDF3_Unity_PBS
    #elif UNITY_PBS_USE_BRDF2
        #define UNITY_BRDF_PBS BRDF2_Unity_PBS
    #elif UNITY_PBS_USE_BRDF1
        #define UNITY_BRDF_PBS BRDF1_Unity_PBS
    #elif defined(SHADER_TARGET_SURFACE_ANALYSIS)
        // we do preprocess pass during shader analysis and we dont actually care about brdf as we need only inputs/outputs
        #define UNITY_BRDF_PBS BRDF1_Unity_PBS
    #else
        #error something broke in auto-choosing BRDF
    #endif
#endif
选个效果最好的BRDF1_Unity_PBS
half4 BRDF1_Unity_PBS (half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness,
    half3 normal, half3 viewDir,
    UnityLight light, UnityIndirect gi)
{
    half perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
    half3 halfDir = Unity_SafeNormalize (light.dir + viewDir);

// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping
// In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
// but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
// Following define allow to control this. Set it to 0 if ALU is critical on your platform.
// This correction is interesting for GGX with SmithJoint visibility function because artifacts are more visible in this case due to highlight edge of rough surface
// Edit: Disable this code by default for now as it is not compatible with two sided lighting used in SpeedTree.
#define UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV 0

#if UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV
    // The amount we shift the normal toward the view vector is defined by the dot product.
    half shiftAmount = dot(normal, viewDir);
    normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
    // A re-normalization should be applied here but as the shift is small we don't do it to save ALU.
    //normal = normalize(normal);

    half nv = saturate(dot(normal, viewDir)); // TODO: this saturate should no be necessary here
#else
    half nv = abs(dot(normal, viewDir));    // This abs allow to limit artifact
#endif

    half nl = saturate(dot(normal, light.dir));
    half nh = saturate(dot(normal, halfDir));

    half lv = saturate(dot(light.dir, viewDir));
    half lh = saturate(dot(light.dir, halfDir));

    // Diffuse term
    half diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;

    // Specular term
    // HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
    // BUT 1) that will make shader look significantly darker than Legacy ones
    // and 2) on engine side "Non-important" lights have to be divided by Pi too in cases when they are injected into ambient SH
    half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
#if UNITY_BRDF_GGX
    half V = SmithJointGGXVisibilityTerm (nl, nv, roughness);
    half D = GGXTerm (nh, roughness);
#else
    // Legacy
    half V = SmithBeckmannVisibilityTerm (nl, nv, roughness);
    half D = NDFBlinnPhongNormalizedTerm (nh, PerceptualRoughnessToSpecPower(perceptualRoughness));
#endif

    half specularTerm = V*D * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later

#   ifdef UNITY_COLORSPACE_GAMMA
        specularTerm = sqrt(max(1e-4h, specularTerm));
#   endif

    // specularTerm * nl can be NaN on Metal in some cases, use max() to make sure it's a sane value
    specularTerm = max(0, specularTerm * nl);
#if defined(_SPECULARHIGHLIGHTS_OFF)
    specularTerm = 0.0;
#endif

    // surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1)
    half surfaceReduction;
#   ifdef UNITY_COLORSPACE_GAMMA
        surfaceReduction = 1.0-0.28*roughness*perceptualRoughness;      // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
#   else
        surfaceReduction = 1.0 / (roughness*roughness + 1.0);           // fade \in [0.5;1]
#   endif

    // To provide true Lambert lighting, we need to be able to kill specular completely.
    specularTerm *= any(specColor) ? 1.0 : 0.0;

    half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
    half3 color =   diffColor * (gi.diffuse + light.color * diffuseTerm)
                    + specularTerm * light.color * FresnelTerm (specColor, lh)
                    + surfaceReduction * gi.specular * FresnelLerp (specColor, grazingTerm, nv);

    return half4(color, 1);
}
UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV为0,走下边分支
UNITY_BRDF_GGX 用
UNITY_COLORSPACE_GAMMA,是gamma空间
_SPECULARHIGHLIGHTS_OFF false
去掉分支,代码如下
half perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
                        half3 halfDir = Unity_SafeNormalize (light.dir + viewDir);
                        half nv = abs(dot(normal, viewDir));    // This abs allow to limit artifact
                        half nl = saturate(dot(normal, light.dir));
                        half nh = saturate(dot(normal, halfDir));

                        half lv = saturate(dot(light.dir, viewDir));
                        half lh = saturate(dot(light.dir, halfDir));

                        // Diffuse term
                        half diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;
                        half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
                        half V = SmithJointGGXVisibilityTerm (nl, nv, roughness);
                        half D = GGXTerm (nh, roughness);
                        half specularTerm = V*D * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later
                        specularTerm = sqrt(max(1e-4h, specularTerm));
                        specularTerm = max(0, specularTerm * nl);
                        half surfaceReduction= 1.0-0.28*roughness*perceptualRoughness;      // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
                        specularTerm *= any(specColor) ? 1.0 : 0.0;
                        half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
                        half3 color =   diffColor * (gi.diffuse + light.color * diffuseTerm)
                                        + specularTerm * light.color * FresnelTerm (specColor, lh)
                                        + surfaceReduction * gi.specular * FresnelLerp (specColor, grazingTerm, nv);

                        return half4(color, 1);

 

最后给下完成代码
Shader "Custom/customstandard" 
{
    Properties 
    {  
        _EmissiveColor("自发光颜色",Color) = (1,1,1,1)
        _EmissiveIntensity("自发光强度",Float) = 1
        
        _LightColor("光照颜色",Color) = (1,1,1,1)
        _LightIntensity("光照强度",Range(0,5)) = 1
        
        _normalScale("法线强度",Float) = 1
        _environment_rotation("环境光贴图旋转",Range(0,360)) = 0
        _RotateSpeed("旋转速度", float) = 1
        _Exposure("环境光曝光值",Float) = 1
        _Skincolor ("Skin Color Custom", Color) = (1,1,1,1)

        _MainTex("颜色贴图", 2D) = "white" {}
        _BumpTex("法线贴图", 2D) = "bump" {}

        _ChannelTex("RGB光滑金属变色", 2D) = "white" {}
        
        _EmissiveMap("自发光贴图", 2D) = "black" {}

        _Cube ("环境光贴图", Cube) = "" {}
        
        _Metallic("金属度上限",Range(0,1))= 1
        _MetallicMin("金属度下限",Range(0,1))= 0
        _Glossiness ("光滑度上限", Range(0,1)) = 1
        _GlossinessMin ("光滑度下限", Range(0,1)) = 0
        //Rim
        _RimColor("轮廓光颜色", Color) = (1, 1, 1, 1)
        _RimArea("轮廓光范围", Range(0, 4)) = 3.6
        _RimPower("轮廓光强度", Range(0, 15)) = 0.0
    }  
    
    
    SubShader 
    {  
        LOD 400
        Lighting Off        
        Tags {"RenderType"="Opaque"}
        
        
        // Pass to render object as a shadow caster
        Pass 
        {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }
            
            ZWrite On ZTest LEqual Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_shadowcaster
            #include "UnityCG.cginc"

            struct v2f { 
                V2F_SHADOW_CASTER;
            };

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

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

        Pass
        {
            Tags { "LightMode" = "ForwardBase" }
            CGPROGRAM
            #pragma vertex   vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            
            struct vertexinput
            {
                float4 vertex   : POSITION;
                half3 normal    : NORMAL;
                float2 uv0      : TEXCOORD0;
                float2 uv1      : TEXCOORD1;
                float2 uv2      : TEXCOORD2;
                half4 tangent   : TANGENT;

            };
            struct v2f
            {
                float4 pos                          : SV_POSITION;
                float4 tex                          : TEXCOORD0;
                half3 eyeVec                        : TEXCOORD1;
                half4 tangentToWorldAndParallax[3]  : TEXCOORD2;    // [3x3:tangentToWorld | 1x3:viewDirForParallax]
                half4 ambientOrLightmapUV           : TEXCOORD5;    // SH or Lightmap UV
                SHADOW_COORDS(6)
                UNITY_FOG_COORDS(7)
                float3 posWorld                     : TEXCOORD8;
                half3 reflUVW                       : TEXCOORD9;
            };
            
            sampler2D _MainTex;
            sampler2D _BumpTex;
            sampler2D _ChannelTex;
            sampler2D _EmissiveMap;
            samplerCUBE _Cube;
            half4 _Cube_HDR;
            
            fixed  _Metallic;
            fixed _MetallicMin;
            fixed _Glossiness;
            fixed _GlossinessMin;
            half _environment_rotation;
            half _RotateSpeed;
            half _Exposure;
            
            half _normalScale;
            fixed4 _LightColor;
            half _LightIntensity;
            
            fixed4 _DLightColor;
            half3 _DLightDir;
            half _DLightIntensity;
            
            half _EmissiveIntensity;
            fixed4 _EmissiveColor;
            
            fixed4 _Skincolor;
            float _RimPower;
            fixed4 _RimColor;
            float _RimArea;
            fixed4 _LightColor0;
            
            v2f vert(vertexinput v)
            {
                v2f o = (v2f)0;
                float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
                o.posWorld = posWorld.xyz;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.tex.xy= v.uv0;
                o.eyeVec = posWorld.xyz - _WorldSpaceCameraPos;
                half3 normalWorld = UnityObjectToWorldNormal(v.normal);
                float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);

                float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
                o.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
                o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
                o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
                //We need this for shadow receving
                TRANSFER_SHADOW(o);
                o.ambientOrLightmapUV.rgb = SHEvalLinearL2Ex(normalWorld);
                o.reflUVW = reflect(o.eyeVec, normalWorld);
                UNITY_TRANSFER_FOG(o, o.pos);
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                UnityLight mainLight;
                mainLight.color = _LightColor0.rgb;
                mainLight.dir = _WorldSpaceLightPos0.xyz;
                mainLight.ndotl = 0; // Not used
                half atten = SHADOW_ATTENUATION(i);
                
                UnityGIInput d;
                d.light = mainLight;
                d.worldPos = i.posWorld;
                half3 worldViewDir  = -normalize(i.eyeVec);
                d.worldViewDir = worldViewDir;
                d.atten = atten;
                d.ambient = i.ambientOrLightmapUV.rgb;
                d.lightmapUV = 0;
                d.probeHDR[0] = unity_SpecCube0_HDR;
                d.probeHDR[1] = unity_SpecCube1_HDR;
                fixed4 channel = tex2D(_ChannelTex, i.tex);
                fixed metallic = _MetallicMin + channel.g * ( _Metallic - _MetallicMin );
                half oneMinusReflectivity;
                half3 specColor;
                fixed colorMask = channel.b;
                fixed4 mainTex  = tex2D(_MainTex,i.tex);
                mainTex *= colorMask * _Skincolor + (1 - colorMask);
                half3 diffColor = DiffuseAndSpecularFromMetallic (mainTex.rgb, metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
                fixed smoothness = ( _GlossinessMin + channel.r * (_Glossiness-_GlossinessMin)  )* 0.99h;
                half3 normalWorld = PerPixelWorldNormal(UnpackScaleNormal(tex2D (_BumpTex, i.tex.xy), _normalScale), i.tangentToWorldAndParallax );
                Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(smoothness, worldViewDir, normalWorld, specColor);
                // Replace the reflUVW if it has been compute in Vertex shader. Note: the compiler will optimize the calcul in UnityGlossyEnvironmentSetup itself
                g.reflUVW = i.reflUVW;
                UnityGI gi = UnityGlobalIllumination (d, 1, normalWorld, g);                
                 half4 c = BRDF(diffColor, specColor, oneMinusReflectivity, smoothness, normalWorld, worldViewDir, gi.light, gi.indirect);
                fixed emimask = tex2D(_EmissiveMap, i.tex).r;
                fixed3 Emissive = emimask * _EmissiveColor.rgb * _EmissiveIntensity;
                float3 _Rim = pow(1.0 - max(0, dot(normalWorld, worldViewDir)), _RimArea)*_RimColor.rgb*_RimPower;
                c.rgb += Emissive + _Rim;
                UNITY_APPLY_FOG(i.fogCoord, c.rgb);
                return c;
            }
            ENDCG

            CGINCLUDE
                    #define unity_ColorSpaceDielectricSpec half4(0.220916301, 0.220916301, 0.220916301, 1.0 - 0.220916301)
                    #define UNITY_INV_PI        0.31830988618f
                    struct UnityLight
                    {
                        half3 color;
                        half3 dir;
                        half  ndotl; // Deprecated: Ndotl is now calculated on the fly and is no longer stored. Do not used it.
                    };
                    
                    struct UnityIndirect
                    {
                        half3 diffuse;
                        half3 specular;
                    };
                    
                    struct UnityGIInput
                    {
                        UnityLight light; // pixel light, sent from the engine

                        float3 worldPos;
                        half3 worldViewDir;
                        half atten;
                        half3 ambient;

                        // interpolated lightmap UVs are passed as full float precision data to fragment shaders
                        // so lightmapUV (which is used as a tmp inside of lightmap fragment shaders) should
                        // also be full float precision to avoid data loss before sampling a texture.
                        float4 lightmapUV; // .xy = static lightmap UV, .zw = dynamic lightmap UV

                        #if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION
                        float4 boxMin[2];
                        #endif
                        #if UNITY_SPECCUBE_BOX_PROJECTION
                        float4 boxMax[2];
                        float4 probePosition[2];
                        #endif
                        // HDR cubemap properties, use to decompress HDR texture
                        float4 probeHDR[2];
                    };
                    struct UnityGI
                    {
                        UnityLight light;
                        #ifdef DIRLIGHTMAP_SEPARATE
                            #ifdef LIGHTMAP_ON
                                UnityLight light2;
                            #endif
                            #ifdef DYNAMICLIGHTMAP_ON
                                UnityLight light3;
                            #endif
                        #endif
                        UnityIndirect indirect;
                    };

                    struct Unity_GlossyEnvironmentData
                    {
                        // - Deferred case have one cubemap
                        // - Forward case can have two blended cubemap (unusual should be deprecated).

                        // Surface properties use for cubemap integration
                        half    roughness; // CAUTION: This is perceptualRoughness but because of compatibility this name can't be change :(
                        half3   reflUVW;
                    };
            
                    Unity_GlossyEnvironmentData UnityGlossyEnvironmentSetup(half Smoothness, half3 worldViewDir, half3 Normal, half3 fresnel0)
                    {
                        Unity_GlossyEnvironmentData g;

                        g.roughness /* perceptualRoughness */   = 1-Smoothness;
                        g.reflUVW   = reflect(-worldViewDir, Normal);

                        return g;
                    }
                    
                    // normal should be normalized, w=1.0
                    half3 SHEvalLinearL0L1Ex (half4 normal)
                    {
                        half3 x;

                        // Linear (L1) + constant (L0) polynomial terms
                        x.r = dot(unity_SHAr,normal);
                        x.g = dot(unity_SHAg,normal);
                        x.b = dot(unity_SHAb,normal);

                        return x;
                    }
                    // normal should be normalized, w=1.0
                    half3 SHEvalLinearL2Ex(half3 normal)
                    {
                        half3 x1, x2;
                        // 4 of the quadratic (L2) polynomials
                        half4 vB = normal.xyzz * normal.yzzx;
                        x1.r = dot(unity_SHBr, vB);
                        x1.g = dot(unity_SHBg, vB);
                        x1.b = dot(unity_SHBb, vB);

                        // Final (5th) quadratic (L2) polynomial
                        half vC = normal.x*normal.x - normal.y*normal.y;
                        x2 = unity_SHC.rgb * vC;

                        return x1 + x2;
                    }

                    
                    inline half3 LinearToGamma (half3 linRGB)
                    {
                        linRGB = max(linRGB, half3(0.h, 0.h, 0.h));
                        // An almost-perfect approximation from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
                        return max(1.055h * pow(linRGB, 0.416666667h) - 0.055h, 0.h);

                        // Exact version, useful for debugging.
                        //return half3(LinearToGammaSpaceExact(linRGB.r), LinearToGammaSpaceExact(linRGB.g), LinearToGammaSpaceExact(linRGB.b));
                    }


                    inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)
                    {
                        UnityGI o_gi;
                        o_gi.light = data.light;
                        o_gi.light.color *= data.atten;
                        o_gi.indirect.diffuse = LinearToGamma( data.ambient + SHEvalLinearL0L1Ex (half4(normalWorld, 1.0)));
                        o_gi.indirect.specular = 0;
                        return o_gi;
                    }

                    inline half3 DiffuseAndSpecularFromMetallic (half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity)
                    {
                        specColor = lerp (unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
                        oneMinusReflectivity = (1-metallic)*unity_ColorSpaceDielectricSpec.a;
                        return albedo * oneMinusReflectivity;
                    } 
                    
                    half3x3 CreateTangentToWorldPerVertex(half3 normal, half3 tangent, half tangentSign)
                    {
                        // For odd-negative scale transforms we need to flip the sign
                        half sign = tangentSign * unity_WorldTransformParams.w;
                        half3 binormal = cross(normal, tangent) * sign;
                        return half3x3(tangent, binormal, normal);
                    }
                    
                    half3 UnpackScaleNormal(half4 packednormal, half bumpScale)
                    {
                        #if defined(UNITY_NO_DXT5nm)
                            return packednormal.xyz * 2 - 1;
                        #else
                            half3 normal;
                            normal.xy = (packednormal.wy * 2 - 1);
                            #if (SHADER_TARGET >= 30)
                                // SM2.0: instruction count limitation
                                // SM2.0: normal scaler is not supported
                                normal.xy *= bumpScale;
                            #endif
                            normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
                            return normal;
                        #endif
                    }
                    half3 PerPixelWorldNormal(half3 normalTangent, half4 tangentToWorld[3])
                    {
                        half3 tangent = tangentToWorld[0].xyz;
                        half3 binormal = tangentToWorld[1].xyz;
                        half3 normal = tangentToWorld[2].xyz;
                        half3 normalWorld = normalize(tangent * normalTangent.x + binormal * normalTangent.y + normal * normalTangent.z); // @TODO: see if we can squeeze this normalize on SM2.0 as well
                        return normalWorld;
                    }
                    
                    inline half SmoothnessToPerceptualRoughness(half smoothness)
                    {
                        return (1 - smoothness);
                    }

                    inline half PerceptualRoughnessToRoughness(half perceptualRoughness)
                    {
                        return perceptualRoughness * perceptualRoughness;
                    }
                    
                    inline half Pow5 (half x)
                    {
                        return x*x * x*x * x;
                    }
                    
                    inline half3 Unity_SafeNormalize(half3 inVec)
                    {
                        half dp3 = max(0.001f, dot(inVec, inVec));
                        return inVec * rsqrt(dp3);
                    }
                    
                    // Note: Disney diffuse must be multiply by diffuseAlbedo / PI. This is done outside of this function.
                    half DisneyDiffuse(half NdotV, half NdotL, half LdotH, half perceptualRoughness)
                    {
                        half fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
                        // Two schlick fresnel term
                        half lightScatter   = (1 + (fd90 - 1) * Pow5(1 - NdotL));
                        half viewScatter    = (1 + (fd90 - 1) * Pow5(1 - NdotV));

                        return lightScatter * viewScatter;
                    }
                    
                    inline half GGXTerm (half NdotH, half roughness)
                    {
                        half a2 = roughness * roughness;
                        half d = (NdotH * a2 - NdotH) * NdotH + 1.0f; // 2 mad
                        return 0.31830988618f * a2 / (d * d + 1e-7f); // This function is not intended to be running on Mobile,
                                                                // therefore epsilon is smaller than what can be represented by half
                    }

                    // Ref: http://jcgt.org/published/0003/02/03/paper.pdf
                    inline half SmithJointGGXVisibilityTerm (half NdotL, half NdotV, half roughness)
                    {
                        half a = roughness;
                        half lambdaV = NdotL * (NdotV * (1 - a) + a);
                        half lambdaL = NdotV * (NdotL * (1 - a) + a);

                        return 0.5f / (lambdaV + lambdaL + 1e-5f);
                    }
                    
                    inline half3 FresnelTerm (half3 F0, half cosA)
                    {
                        half t = Pow5 (1 - cosA);   // ala Schlick interpoliation
                        return F0 + (1-F0) * t;
                    }
                    inline half3 FresnelLerp (half3 F0, half3 F90, half cosA)
                    {
                        half t = Pow5 (1 - cosA);   // ala Schlick interpoliation
                        return lerp (F0, F90, t);
                    }

                    inline half4 BRDF(half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness,half3 normal, half3 viewDir,UnityLight light, UnityIndirect gi)
                    {
                        half perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
                        half3 halfDir = Unity_SafeNormalize (light.dir + viewDir);
                        half nv = abs(dot(normal, viewDir));    // This abs allow to limit artifact
                        half nl = saturate(dot(normal, light.dir));
                        half nh = saturate(dot(normal, halfDir));

                        half lv = saturate(dot(light.dir, viewDir));
                        half lh = saturate(dot(light.dir, halfDir));

                        // Diffuse term
                        half diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;
                        half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
                        half V = SmithJointGGXVisibilityTerm (nl, nv, roughness);
                        half D = GGXTerm (nh, roughness);
                        half specularTerm = V*D * 3.14159265359f; // Torrance-Sparrow model, Fresnel is applied later
                        specularTerm = sqrt(max(1e-4h, specularTerm));
                        specularTerm = max(0, specularTerm * nl);
                        half surfaceReduction= 1.0-0.28*roughness*perceptualRoughness;      // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
                        specularTerm *= any(specColor) ? 1.0 : 0.0;
                        half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
                        half3 color =   diffColor * (gi.diffuse + light.color * diffuseTerm)
                                        + specularTerm * light.color * FresnelTerm (specColor, lh)
                                        + surfaceReduction * gi.specular * FresnelLerp (specColor, grazingTerm, nv);

                        return half4(color, 1);
                    }
            ENDCG
        } 
    }
}

不过还有点问题,回头查下

 

posted on 2018-08-27 16:41  marcher  阅读(548)  评论(0编辑  收藏  举报

导航