自己动手写PBR

下面的shader参照博客修改而成:改动的地方用此颜色表示

代码参照:

unity build-in管线中的PBR材质Shader分析研究_郭大钦的博客-CSDN博客_shader 支持pbr材质以及cubemap  unity build-in管线中的PBR材质Shader分析研究_bulit-in pbr-CSDN博客

最终效果如下:左边是手写的,右边是unity内置standard

自己动手写PBR_第1张图片

1.原shader没有阴影,根据精要我在此基础上添加了阴影.

2.原shader由于作者追求尽量与unity内置standard效果一致,所以有些公式是按照unity独特方式写的,而且是最高质量的计算方式 ,因此有些算法还可以精简,再就是他把函数都展开写到片元着色器里面了,比较难看.有待改进.

3.仅有不透明物体的计算方式.

4.金属度,粗糙度只有数值调节,没有贴图控制.待完善.

Shader "Custom/myPBR"
{
    Properties
    {
        _Tint("Tint",Color)=(1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
        //金属度要经过gama,否则即便是linear空间下渲染,unity也不会对一个滑条做操作的
        [Gamma]_Metallic("Metallic",Range(0,1))=0
        _MetallicGlossMap("Metallic", 2D) = "white" {}
        _Smoothness("Smoothness(Metallic.a)",Range(0,1))=0.5
        _BumpMap("Normal Map", 2D) = "bump" {}
        _Parallax ("Height Scale", Range (0.00, 0.08)) = 0.0
        _ParallaxMap ("Height Map", 2D) = "black" {}
        _OcclusionMap("Occlusion", 2D) = "white" {}
    }
    SubShader
    {
        Pass
        {
            Tags{"LightMode"="ForwardBase"}
            CGPROGRAM
            // 加上下面这行
            #pragma multi_compile_fwdbase
            #pragma vertex vert
            #pragma fragment frag
            //添加lightmap支持
            #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
            #include "UnityStandardBRDF.cginc"
            // 加上下面这行,不然没有阴影
            #include "AutoLight.cginc"
            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal:NORMAL;
                float2 uv : TEXCOORD0;
                float2 uv1:TEXCOORD1;
                fixed4 tangent : TANGENT;
            };
            struct v2f
            {
                float2 uv : TEXCOORD0;
                #ifndef LIGHTMAP_OFF
                    half2 uv1:TEXCOORD1;
                #endif
                //float4 vertex : SV_POSITION;
                float4 pos : SV_POSITION;//修改为pos
                float3 normal:TEXCOORD2;
                float3 worldPos:TEXCOORD3;
                float4 tangent:TEXCOORD4;
                float3x3 tangentToWorld : TEXCOORD5;
                float3 viewDir:COLOR1;
                float3x3 tangentMatrix: TEXCOORD8;
                float3 objectspaceViewdir:COLOR2;
                SHADOW_COORDS(11)//三剑客1. 注意括号里面的数字(11)========================================================================================
            };
            sampler2D _MainTex;
            float4 _Tint;
            float _Metallic;
            float _Smoothness;
            float4 _MainTex_ST;
            sampler2D _MetallicGlossMap;
            sampler2D _BumpMap;
            sampler2D _OcclusionMap;
            float _Parallax;
            sampler2D _ParallaxMap;
            inline half OneMinusReflectivityFromMetallic(half metallic)
            {
                // We'll need oneMinusReflectivity, so
                //   1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) =  lerp(1-dielectricSpec, 0, metallic)
                // store (1-dielectricSpec) in unity_ColorSpaceDielectricSpec.a, then
                //   1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) =
                //                  = alpha - metallic * alpha
                half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
                return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
            }
            inline half3 DiffuseAndSpecularFromMetallic (half3 albedo, half metallic, out  half3 specColor, out half oneMinusReflectivity)
            {
                specColor = lerp (unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
                oneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic);
                return albedo * oneMinusReflectivity;
            }
            v2f vert (appdata v)
            {
                v2f o;
                //o.vertex = UnityObjectToClipPos(v.vertex);
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.normal = UnityObjectToWorldNormal(v.normal);
                o.normal = normalize(o.normal);
                o.tangent=v.tangent;
                float3 normalWorld =  UnityObjectToWorldNormal(v.normal);
                float4 tangentWorld =  float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
                // 对于奇怪的负缩放,我们需要sign取反(flip the sign)
                half sign = tangentWorld.w *  unity_WorldTransformParams.w;
                half3 binormal = cross(normalWorld, tangentWorld) *  sign;
                float3x3 tangentToWorld = half3x3(tangentWorld.xyz,  binormal, normalWorld);
                o.tangentToWorld=tangentToWorld;
                o.viewDir=normalize(UnityWorldSpaceViewDir(o.worldPos));
                //Parallax viewDir need to changed from ObjectSpace to  Tangent
                fixed3 worldViewDir =  normalize(UnityWorldSpaceViewDir(o.worldPos));
                fixed3 objectspaceViewdir= mul(unity_WorldToObject, worldViewDir);
                o.objectspaceViewdir =normalize(objectspaceViewdir);
                float3 objectSpaceBinormal = normalize(cross(v.normal,v.tangent.xyz)  * v.tangent.w);
                float3x3 tangentMatrix = float3x3(v.tangent.xyz,  objectSpaceBinormal, v.normal);
                o.tangentMatrix = tangentMatrix;
                #ifndef LIGHTMAP_OFF
                    o.uv1 = v.uv1.xy*unity_LightmapST.xy +  unity_LightmapST.zw;
                #endif
                TRANSFER_SHADOW(o);//三剑客2================================================================================================================
                //重点!! 由于计算阴影的这些宏会使用上下文的变量进行相关的计算!!!!
                //这里的TRANSFER_SHADOW就会使用到 v.vertex或a.pos来计算
                //因此必须保证自定义的变量名和这些宏使用的变量名相匹配!!!!!!!
                //SO! appdata结构中的顶点坐标必须是 vertex !
                //顶点着色器的输出结构体 v2f 必须命名为 v !
                //v2f中顶点位置必须是pos !
                //否则会出现以下报错
                //invalid subscript 'pos' 'ComputeScreenPos': no  matching 1 parameter function
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                #ifndef LIGHTMAP_OFF
                    fixed3 lm =  DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap,i.uv1));
                    float3 albedo = _Tint*tex2D(_MainTex,i.uv);
                    float3 finalRes = albedo * lm;
                    return float4( finalRes,1);
                #endif
                half height = tex2D(_ParallaxMap, i.uv).g;
                float3 tangentspaceViewDir =normalize( mul(i.tangentMatrix,  i.objectspaceViewdir));
                i.uv += ParallaxOffset(height,_Parallax,tangentspaceViewDir);
                _Metallic=tex2D(_MetallicGlossMap,i.uv).r*_Metallic;
                _Smoothness=tex2D(_MetallicGlossMap,i.uv).a*_Smoothness;
                float occlusion=tex2D(_OcclusionMap,i.uv).r;
                float3 normal = normalize(i.normal);//没有加normalize操作,导致其还是取的顶点法线,没有进行插值
                //     #ifdef _NORMALMAP
                half3 tangent1 = i.tangentToWorld[0].xyz;
                half3 binormal1 = i.tangentToWorld[1].xyz;
                half3 normal1 = i.tangentToWorld[2].xyz;
                float3 normalTangent  =UnpackNormal(tex2D(_BumpMap,i.uv));
                //return float4(1,0,0,1);
                //                   normal= normalize(float3(dot(i.TtoW0.xyz,  normalTangent), dot(i.TtoW1.xyz, normalTangent), dot(i.TtoW2.xyz,  normalTangent)));//矩阵变换
                normal=normalize((float3)(tangent1 * normalTangent.x +  binormal1 * normalTangent.y + normal1 * normalTangent.z));
                // #endif
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                //float3 viewDir = normalize(_WorldSpaceCameraPos.xyz  - i.worldPos.xyz);
                //            float3 viewDir =  normalize(UnityWorldSpaceViewDir(i.worldPos));
                float3 viewDir=i.viewDir;
                float3 lightColor = _LightColor0.rgb;
                float3 halfVector = normalize(lightDir + viewDir);
                //roughness相关
                float perceptualRoughness = 1 - _Smoothness;
                float roughness = perceptualRoughness *  perceptualRoughness;
                roughness=max(roughness,0.002);//即便smoothness为1,也要有点高光在
                float squareRoughness = roughness * roughness;
                float nl = max(saturate(dot(normal , lightDir ) ) ,  0.0000001);//防止除0
                float nv = max(saturate(dot(normal, viewDir)),  0.0000001);
                float vh = max(saturate(dot(viewDir, halfVector)),  0.0000001);
                float lh = max(saturate(dot(lightDir, halfVector)),  0.0000001);
                float nh = max(saturate(dot(normal, halfVector)),  0.0000001);
               
                //1.1直接光漫反射部分.兰伯特光照。没有除以π,是因为会显得太暗。
                float3 Albedo = _Tint*tex2D(_MainTex,i.uv);
                //float3 rawDiffColor =  DisneyDiffuse(nv,nl,lh,perceptualRoughness)*nl*lightColor;
                float3 rawDiffColor =  nl*lightColor;//去掉了影响不大的"高级运算"
                //1.2.直接光镜面反射部分
                // 1.2.1 D项(GGX)
                float D=GGXTerm(nh,roughness);
                // 1.2.2 G项 几何函数,遮蔽变暗一些
                //      直接光照和间接光照时的k都在逼近二分之一,只不过直接光照时这个值最小为八分之一而不是0。这是为了保证在表面绝对光滑时
                //      也会吸收一部分光线,毕竟完全不吸收光线的物体在现实中不存在
                float G=SmithJointGGXVisibilityTerm(nl,nv,roughness);
                //1.2.3 F项 菲涅尔反射 金属反射强边缘反射强
                float3 F0 = lerp(unity_ColorSpaceDielectricSpec.rgb,  Albedo, _Metallic);
                float3 F=FresnelTerm(F0,lh);
                //漫反射系数kd
                float3 kd =  OneMinusReflectivityFromMetallic(_Metallic);
                kd*=Albedo;
               
                float3 specular = D * G * F ;
                float3 specColor = specular *  lightColor*nl*UNITY_PI;//直接光镜面反射部分。镜面反射的系数就是F。漫反射之前少除π了,所以为了保证漫反射和镜面反射的比例,这里还得乘一个π
                float3 diffColor = kd * rawDiffColor;//直接光漫反射部分。
                float3 directLightResult = diffColor + specColor;
                //至此,直接光部分结束





               
                //2.开始间接光部分:注意间接光的漫反射需要设置光照探针,间接光的镜面反射需要设置反射探针.
                //     2.1间接光漫反射
                half3 iblDiffuse = ShadeSH9(float4(normal,1));
                float3 iblDiffuseResult = iblDiffuse*kd;//乘间接光漫反射系数
                //     2.2间接光镜面反射
                float mip_roughness = perceptualRoughness * (1.7 -  0.7*perceptualRoughness );
                float3 reflectVec = reflect(-viewDir, normal);
                half mip = mip_roughness *  UNITY_SPECCUBE_LOD_STEPS;//得出mip层级。默认UNITY_SPECCUBE_LOD_STEPS=6(定义在UnityStandardConfig.cginc)
                half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0,  reflectVec, mip);//视线方向的反射向量,去取样,同时考虑mip层级
                half3 iblSpecular = DecodeHDR(rgbm,  unity_SpecCube0_HDR);//使用DecodeHDR将颜色从HDR编码下解码。可以看到采样出的rgbm是一个4通道的值,
                half surfaceReduction=1.0/(roughness*roughness+1.0);
                float oneMinusReflectivity =  unity_ColorSpaceDielectricSpec.a-unity_ColorSpaceDielectricSpec.a*_Metallic;      //grazingTerm压暗非金属的边缘异常高亮
                half  grazingTerm=saturate(_Smoothness+(1-oneMinusReflectivity));
                float3 iblSpecularResult =  surfaceReduction*iblSpecular*FresnelLerp(F0,grazingTerm,nv);
                float3 indirectResult = (iblDiffuseResult +  iblSpecularResult)*occlusion;
                //至此,结束间接光部分
               
               
                fixed shadow = SHADOW_ATTENUATION(i);//三剑客3===============================================================================================
                //最终加和
                float3 finalResult = directLightResult*shadow +  indirectResult;//在直接光后面加了 *shadow
                return float4(finalResult,1);
               
            }
            ENDCG
        }
    }
    FallBack"Diffuse"
}

以下代码和上面完全相同,但是用红色标出了我自己添加的阴影功能,

Shader "Custom/myPBR"
{
    Properties
    {
        _Tint("Tint",Color)=(1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
        //金属度要经过gama,否则即便是linear空间下渲染,unity也不会对一个滑条做操作的
        [Gamma]_Metallic("Metallic",Range(0,1))=0
        _MetallicGlossMap("Metallic", 2D) = "white" {}
        _Smoothness("Smoothness(Metallic.a)",Range(0,1))=0.5
        _BumpMap("Normal Map", 2D) = "bump" {}
        _Parallax ("Height Scale", Range (0.00, 0.08)) = 0.0
        _ParallaxMap ("Height Map", 2D) = "black" {}
        _OcclusionMap("Occlusion", 2D) = "white" {}
    }
    SubShader
    {
        Pass
        {
            Tags{"LightMode"="ForwardBase"}
            CGPROGRAM
            // 加上下面这行
            #pragma multi_compile_fwdbase
            #pragma vertex vert
            #pragma fragment frag
            //添加lightmap支持
            #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
            #include "UnityStandardBRDF.cginc"
            // 加上下面这行,不然没有阴影
            #include "AutoLight.cginc"
            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal:NORMAL;
                float2 uv : TEXCOORD0;
                float2 uv1:TEXCOORD1;
                fixed4 tangent : TANGENT;
            };
            struct v2f
            {
                float2 uv : TEXCOORD0;
                #ifndef LIGHTMAP_OFF
                    half2 uv1:TEXCOORD1;
                #endif
                //float4 vertex : SV_POSITION;
                float4 pos : SV_POSITION;//修改为pos
                float3 normal:TEXCOORD2;
                float3 worldPos:TEXCOORD3;
                float4 tangent:TEXCOORD4;
                float3x3 tangentToWorld : TEXCOORD5;
                float3 viewDir:COLOR1;
                float3x3 tangentMatrix: TEXCOORD8;
                float3 objectspaceViewdir:COLOR2;
                 SHADOW_COORDS(11)//三剑客1. 注意括号里面的数字================
            };
            sampler2D _MainTex;
            float4 _Tint;
            float _Metallic;
            float _Smoothness;
            float4 _MainTex_ST;
            sampler2D _MetallicGlossMap;
            sampler2D _BumpMap;
            sampler2D _OcclusionMap;
            float _Parallax;
            sampler2D _ParallaxMap;
            inline half OneMinusReflectivityFromMetallic(half metallic)
            {
                // We'll need oneMinusReflectivity, so
                //   1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) =  lerp(1-dielectricSpec, 0, metallic)
                // store (1-dielectricSpec) in unity_ColorSpaceDielectricSpec.a, then
                //   1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) =
                //                  = alpha - metallic * alpha
                half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
                return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
            }
            inline half3 DiffuseAndSpecularFromMetallic (half3 albedo, half metallic, out  half3 specColor, out half oneMinusReflectivity)
            {
                specColor = lerp (unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
                oneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic);
                return albedo * oneMinusReflectivity;
            }
            v2f vert (appdata v)
            {
                v2f o;
                 //o.vertex = UnityObjectToClipPos(v.vertex);
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.normal = UnityObjectToWorldNormal(v.normal);
                o.normal = normalize(o.normal);
                o.tangent=v.tangent;
                float3 normalWorld =  UnityObjectToWorldNormal(v.normal);
                float4 tangentWorld =  float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
                // 对于奇怪的负缩放,我们需要sign取反(flip the sign)
                half sign = tangentWorld.w *  unity_WorldTransformParams.w;
                half3 binormal = cross(normalWorld, tangentWorld) *  sign;
                float3x3 tangentToWorld = half3x3(tangentWorld.xyz,  binormal, normalWorld);
                o.tangentToWorld=tangentToWorld;
                o.viewDir=normalize(UnityWorldSpaceViewDir(o.worldPos));
                //Parallax viewDir need to changed from ObjectSpace to  Tangent
                fixed3 worldViewDir =  normalize(UnityWorldSpaceViewDir(o.worldPos));
                fixed3 objectspaceViewdir= mul(unity_WorldToObject, worldViewDir);
                o.objectspaceViewdir =normalize(objectspaceViewdir);
                float3 objectSpaceBinormal = normalize(cross(v.normal,v.tangent.xyz)  * v.tangent.w);
                float3x3 tangentMatrix = float3x3(v.tangent.xyz,  objectSpaceBinormal, v.normal);
                o.tangentMatrix = tangentMatrix;
                #ifndef LIGHTMAP_OFF
                    o.uv1 = v.uv1.xy*unity_LightmapST.xy +  unity_LightmapST.zw;
                #endif
                 TRANSFER_SHADOW(o);//三剑客2===========================
                //重点!! 由于计算阴影的这些宏会使用上下文的变量进行相关的计算!!!!
                //这里的TRANSFER_SHADOW就会使用到 v.vertex或a.pos来计算
                //因此必须保证自定义的变量名和这些宏使用的变量名相匹配!!!!!!!
                //SO! appdata结构中的顶点坐标必须是 vertex !
                //顶点着色器的输出结构体 v2f 必须命名为 v !
                //v2f中顶点位置必须是pos !
                //否则会出现以下报错
                //invalid subscript 'pos' 'ComputeScreenPos': no  matching 1 parameter function
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                #ifndef LIGHTMAP_OFF
                    fixed3 lm =  DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap,i.uv1));
                    float3 albedo = _Tint*tex2D(_MainTex,i.uv);
                    float3 finalRes = albedo * lm;
                    return float4( finalRes,1);
                #endif
                half height = tex2D(_ParallaxMap, i.uv).g;
                float3 tangentspaceViewDir =normalize( mul(i.tangentMatrix,  i.objectspaceViewdir));
                i.uv += ParallaxOffset(height,_Parallax,tangentspaceViewDir);
                _Metallic=tex2D(_MetallicGlossMap,i.uv).r*_Metallic;
                _Smoothness=tex2D(_MetallicGlossMap,i.uv).a*_Smoothness;
                float occlusion=tex2D(_OcclusionMap,i.uv).r;
                float3 normal = normalize(i.normal);//没有加normalize操作,导致其还是取的顶点法线,没有进行插值
                //     #ifdef _NORMALMAP
                half3 tangent1 = i.tangentToWorld[0].xyz;
                half3 binormal1 = i.tangentToWorld[1].xyz;
                half3 normal1 = i.tangentToWorld[2].xyz;
                float3 normalTangent  =UnpackNormal(tex2D(_BumpMap,i.uv));
                //return float4(1,0,0,1);
                //                   normal= normalize(float3(dot(i.TtoW0.xyz,  normalTangent), dot(i.TtoW1.xyz, normalTangent), dot(i.TtoW2.xyz,  normalTangent)));//矩阵变换
                normal=normalize((float3)(tangent1 * normalTangent.x +  binormal1 * normalTangent.y + normal1 * normalTangent.z));
                // #endif
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                //float3 viewDir = normalize(_WorldSpaceCameraPos.xyz  - i.worldPos.xyz);
                //            float3 viewDir =  normalize(UnityWorldSpaceViewDir(i.worldPos));
                float3 viewDir=i.viewDir;
                float3 lightColor = _LightColor0.rgb;
                float3 halfVector = normalize(lightDir + viewDir);
                //roughness相关
                float perceptualRoughness = 1 - _Smoothness;
                float roughness = perceptualRoughness *  perceptualRoughness;
                roughness=max(roughness,0.002);//即便smoothness为1,也要有点高光在
                float squareRoughness = roughness * roughness;
                float nl = max(saturate(dot(normal , lightDir ) ) ,  0.0000001);//防止除0
                float nv = max(saturate(dot(normal, viewDir)),  0.0000001);
                float vh = max(saturate(dot(viewDir, halfVector)),  0.0000001);
                float lh = max(saturate(dot(lightDir, halfVector)),  0.0000001);
                float nh = max(saturate(dot(normal, halfVector)),  0.0000001);
               
                //1.1直接光漫反射部分.兰伯特光照。没有除以π,是因为会显得太暗。
                float3 Albedo = _Tint*tex2D(_MainTex,i.uv);
                 //float3 rawDiffColor =  DisneyDiffuse(nv,nl,lh,perceptualRoughness)*nl*lightColor;
                float3 rawDiffColor =  nl*lightColor;//去掉了影响不大的"高级运算"
                //1.2.直接光镜面反射部分
                // 1.2.1 D项(GGX)
                float D=GGXTerm(nh,roughness);
                // 1.2.2 G项 几何函数,遮蔽变暗一些
                //      直接光照和间接光照时的k都在逼近二分之一,只不过直接光照时这个值最小为八分之一而不是0。这是为了保证在表面绝对光滑时
                //      也会吸收一部分光线,毕竟完全不吸收光线的物体在现实中不存在
                float G=SmithJointGGXVisibilityTerm(nl,nv,roughness);
                //1.2.3 F项 菲涅尔反射 金属反射强边缘反射强
                float3 F0 = lerp(unity_ColorSpaceDielectricSpec.rgb,  Albedo, _Metallic);
                float3 F=FresnelTerm(F0,lh);
                //漫反射系数kd
                float3 kd =  OneMinusReflectivityFromMetallic(_Metallic);
                kd*=Albedo;
               
                float3 specular = D * G * F ;
                float3 specColor = specular *  lightColor*nl*UNITY_PI;//直接光镜面反射部分。镜面反射的系数就是F。漫反射之前少除π了,所以为了保证漫反射和镜面反射的比例,这里还得乘一个π
                float3 diffColor = kd * rawDiffColor;//直接光漫反射部分。
                float3 directLightResult = diffColor + specColor;
                //至此,直接光部分结束
               
                //2.开始间接光部分:注意间接光的漫反射需要设置光照探针,间接光的镜面反射需要设置反射探针.
                //     2.1间接光漫反射
                half3 iblDiffuse = ShadeSH9(float4(normal,1));
                float3 iblDiffuseResult = iblDiffuse*kd;//乘间接光漫反射系数
                //     2.2间接光镜面反射
                float mip_roughness = perceptualRoughness * (1.7 -  0.7*perceptualRoughness );
                float3 reflectVec = reflect(-viewDir, normal);
                half mip = mip_roughness *  UNITY_SPECCUBE_LOD_STEPS;//得出mip层级。默认UNITY_SPECCUBE_LOD_STEPS=6(定义在UnityStandardConfig.cginc)
                half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0,  reflectVec, mip);//视线方向的反射向量,去取样,同时考虑mip层级
                half3 iblSpecular = DecodeHDR(rgbm,  unity_SpecCube0_HDR);//使用DecodeHDR将颜色从HDR编码下解码。可以看到采样出的rgbm是一个4通道的值,
                half surfaceReduction=1.0/(roughness*roughness+1.0);
                float oneMinusReflectivity =  unity_ColorSpaceDielectricSpec.a-unity_ColorSpaceDielectricSpec.a*_Metallic;      //grazingTerm压暗非金属的边缘异常高亮
                half  grazingTerm=saturate(_Smoothness+(1-oneMinusReflectivity));
                float3 iblSpecularResult =  surfaceReduction*iblSpecular*FresnelLerp(F0,grazingTerm,nv);
                float3 indirectResult = (iblDiffuseResult +  iblSpecularResult)*occlusion;
                //至此,结束间接光部分
               
               
                 fixed shadow = SHADOW_ATTENUATION(i);//三剑客3=====================
                //最终加和
                 float3 finalResult = directLightResult*shadow +  indirectResult;//在直接光后面加了 *shadow
                return float4(finalResult,1);
               
            }
            ENDCG
        }
    }
    FallBack"Diffuse"
}

你可能感兴趣的:(unity,shader,pbr,带阴影)