镜面反射

【Unity Shaders】学习笔记——SurfaceShader(十)镜面反射

  1. 倘若您想从零开首学习Unity
    Shader,那么你能够看看本系列的篇章入门,你只必要多少有点编制程序的定义就能够。

  2. 水平有限,难免有荒唐之处,望提出。


【Unity Shaders】学习笔记——SurfaceShader(十)镜面反射

  1. 如若您想从零发轫学习Unity
    Shader,那么你能够看看本种类的篇章入门,你只须要某个有点编制程序的定义就可以。

  2. 水平有限,难免有荒唐之处,望建议。


Unity内置的高光函数

Unity内置了一种高光光照模型——BlinnPhone。
选拔格局如下:

Shader "Custom/BlinnPhong"{
    Properties 
    {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _SpecColor ("Specular Color", Color) = (1,1,1,1)
        _SpecPower ("Specular Power", Range(0,1)) = 0.5
    }

    SubShader 
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf BlinnPhong

        sampler2D _MainTex;
        float _SpecPower;
        float4 _MainTint;

        struct Input 
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            o.Specular = _SpecPower;
            o.Gloss = 1.0;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

应用内置的晋中函数正是要在#pragma里声称它。
_SpecColor是Unity内置的一个变量,在Properties里声称是为了能够在Inspector面板里调节它,所以在末端大家没有应用那几个变量。它控制高光的颜色。
BlinnPhone是Phone光照模型的改善,要读书这几个光照模型先来上学Phone光照模型呢。

Unity内置的高光函数

Unity内置了一种高光光照模型——BlinnPhone。
运用格局如下:

Shader "Custom/BlinnPhong"{
    Properties 
    {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _SpecColor ("Specular Color", Color) = (1,1,1,1)
        _SpecPower ("Specular Power", Range(0,1)) = 0.5
    }

    SubShader 
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf BlinnPhong

        sampler2D _MainTex;
        float _SpecPower;
        float4 _MainTint;

        struct Input 
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            o.Specular = _SpecPower;
            o.Gloss = 1.0;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

动用内置的普照函数正是要在#pragma里声称它。
_SpecColor是Unity内置的一个变量,在Properties里声称是为着能够在Inspector面板里调节它,所以在后边我们从没行使那几个变量。它决定高光的颜料。
BlinnPhone是Phone光照模型的改正,要学习那么些光照模型先来上学Phone光照模型呢。

Phone光照模型

Phone光照模型正是叫Phone的人发明的娄底模型。
代码如下:

Shader "Custom/Phong" {
    Properties 
    {
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _SpecularColor ("Specular Color", Color) = (1,1,1,1)
        _SpecPower ("Specular Power", Range(0.1,30)) = 1
    }

    SubShader 
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Phong

        float4 _SpecularColor;
        sampler2D _MainTex;
        float4 _MainTint;
        float _SpecPower;

        inline fixed4 LightingPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
        {
            //Calculate diffuse and the reflection vector
            float diff = dot(s.Normal, lightDir);
            float3 reflectionVector = normalize((2.0 * s.Normal * diff) - lightDir);

            //Calculate the Phong specular
            float spec = pow(max(0,dot(reflectionVector, viewDir)), _SpecPower);
            float3 finalSpec = _SpecularColor.rgb * spec;

            //Create final color
            fixed4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb * diff) + (_LightColor0.rgb * finalSpec);
            c.a = 1.0;
            return c;
        }

        struct Input 
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

Phone光照模型

Phone光照模型正是叫Phone的人表明的普照模型。
代码如下:

Shader "Custom/Phong" {
    Properties 
    {
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _SpecularColor ("Specular Color", Color) = (1,1,1,1)
        _SpecPower ("Specular Power", Range(0.1,30)) = 1
    }

    SubShader 
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Phong

        float4 _SpecularColor;
        sampler2D _MainTex;
        float4 _MainTint;
        float _SpecPower;

        inline fixed4 LightingPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
        {
            //Calculate diffuse and the reflection vector
            float diff = dot(s.Normal, lightDir);
            float3 reflectionVector = normalize((2.0 * s.Normal * diff) - lightDir);

            //Calculate the Phong specular
            float spec = pow(max(0,dot(reflectionVector, viewDir)), _SpecPower);
            float3 finalSpec = _SpecularColor.rgb * spec;

            //Create final color
            fixed4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb * diff) + (_LightColor0.rgb * finalSpec);
            c.a = 1.0;
            return c;
        }

        struct Input 
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

Phone光照模型解析

reflectionVector是反射光向量。float3 reflectionVector = normalize((2.0 * s.Normal * diff) - lightDir);
正是由法线、入射光向量求反射光向量的方法。
演绎如下图:
图片 1
末尾总计反射向量和观测向量的点积时用max函数是为着背向视线的地点未必太黑。
末尾的水彩正是漫反射颜色加上镜头面反射颜色。

Phone光照模型解析

reflectionVector是反射光向量。float3 reflectionVector = normalize((2.0 * s.Normal * diff) - lightDir);
正是由法线、入射光向量求反射光向量的点子。
演绎如下图:
图片 2
背后总括反射向量和观测向量的点积时用max函数是为着背向视线的地点未必太黑。
最后的颜色正是漫反射颜色加上镜面反射颜色。

BlinnPhone光照模型

BlinnPhone光照模型就是叫Blinn的人立异了Phone光照模型。
在CGIncludes文件夹下Lighting.cginc文件里有BlinnPhone光照函数的定义:

inline fixed4 UnityBlinnPhongLight (SurfaceOutput s, half3 viewDir, UnityLight light)
{
    half3 h = normalize (light.dir + viewDir);

    fixed diff = max (0, dot (s.Normal, light.dir));

    float nh = max (0, dot (s.Normal, h));
    float spec = pow (nh, s.Specular*128.0) * s.Gloss;

    fixed4 c;
    c.rgb = s.Albedo * light.color * diff + light.color * _SpecColor.rgb * spec;
    c.a = s.Alpha;

    return c;
}

h是半角向量。半角向量正是平均七个向量之间夹角的单位向量。七个向量相加,结果是八个向量构成的平行四边形的对角线,所以半角向量是四个向量相加。
BlinnPhone的惜墨如金便是毫无反射向量去总括镜面反射,而是用入射光向量和着眼向量的半角向量来取代计算。这一措施也是一向不物理根据的,只是那样测算总括量更少而且意义差不离甚至更好。近日的着色器十有八九会选取它。
在这里Phone(左)和BlinnPhone(右)的对比:
图片 3

BlinnPhone光照模型

BlinnPhone光照模型便是叫Blinn的人立异了Phone光照模型。
在CGIncludes文件夹下Lighting.cginc文件里有BlinnPhone光照函数的概念:

inline fixed4 UnityBlinnPhongLight (SurfaceOutput s, half3 viewDir, UnityLight light)
{
    half3 h = normalize (light.dir + viewDir);

    fixed diff = max (0, dot (s.Normal, light.dir));

    float nh = max (0, dot (s.Normal, h));
    float spec = pow (nh, s.Specular*128.0) * s.Gloss;

    fixed4 c;
    c.rgb = s.Albedo * light.color * diff + light.color * _SpecColor.rgb * spec;
    c.a = s.Alpha;

    return c;
}

h是半角向量。半角向量正是平均五个向量之间夹角的单位向量。五个向量相加,结果是多个向量构成的平行四边形的对角线,所以半角向量是七个向量相加。
BlinnPhone的校对便是不用反射向量去总结镜面反射,而是用入射光向量和考察向量的半角向量来替代计算。这一措施也是尚未物理依据的,只是那样总计总结量更少而且效果大约甚至更好。最近的着色器十有八九会使用它。
在这里Phone(左)和BlinnPhone(右)的对比:
图片 4

利用贴图对模型的高光实行遮罩

行使高光贴图技术正是行使贴图来支配高光的颜料和强度。那里运用了自定义的SurfaceOutput,总括办法和Phone模型大约,只是透过surf函数将高光遮罩贴图的像素音讯传给了光照模型:

Shader "Custom/CustomPhone" {
    Properties {
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _SpecularColor ("Specular Tint", Color) = (1,1,1,1)
        _SpecularMask ("Specular Texture", 2D) = "white"{}
        _SpecPower("Specular Power", Range(0.1, 120)) = 3
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf CustomPhong

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _SpecularMask;
        float4 _MainTint;
        float4 _SpecularColor;
        float _SpecPower;

        struct Input {
            float2 uv_MainTex;
            float2 uv_SpecularMask;
        };

        struct SurfaceCustomOutput
        {
            fixed3 Albedo;
            fixed3 Normal;
            fixed3 Emission;
            fixed3 SpecularColor;
            half Specular;
            fixed Gloss;
            fixed Alpha;
        };

        inline fixed4 LightingCustomPhong(SurfaceCustomOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
        {
            // Calculate diffuse and the reflection vector
            float diff = dot(s.Normal, lightDir);
            float3 reflectionVector = normalize(2.0 * s.Normal * diff - lightDir);

            // Calculate the Phong specular
            float spec = pow(max(0.0f, dot(reflectionVector, viewDir)), _SpecPower) * s.Specular;
            float3 finalSpec = s.SpecularColor * spec * _SpecularColor.rgb;

            // Create final color
            fixed4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb * diff) + (_LightColor0.rgb * finalSpec);
            c.a = s.Alpha;
            return c;
        }

        void surf(Input IN, inout SurfaceCustomOutput o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            float4 specMask = tex2D(_SpecularMask, IN.uv_SpecularMask) * _SpecularColor;

            o.Albedo = c.rgb;
            o.Specular = specMask.r;
            o.SpecularColor = specMask.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

接纳贴图对模型的高光实行遮罩

选择高光贴图技术便是使用贴图来支配高光的颜色和强度。那里运用了自定义的SurfaceOutput,总结格局和Phone模型大致,只是透过surf函数将高光遮罩贴图的像素新闻传给了光照模型:

Shader "Custom/CustomPhone" {
    Properties {
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _SpecularColor ("Specular Tint", Color) = (1,1,1,1)
        _SpecularMask ("Specular Texture", 2D) = "white"{}
        _SpecPower("Specular Power", Range(0.1, 120)) = 3
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf CustomPhong

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _SpecularMask;
        float4 _MainTint;
        float4 _SpecularColor;
        float _SpecPower;

        struct Input {
            float2 uv_MainTex;
            float2 uv_SpecularMask;
        };

        struct SurfaceCustomOutput
        {
            fixed3 Albedo;
            fixed3 Normal;
            fixed3 Emission;
            fixed3 SpecularColor;
            half Specular;
            fixed Gloss;
            fixed Alpha;
        };

        inline fixed4 LightingCustomPhong(SurfaceCustomOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
        {
            // Calculate diffuse and the reflection vector
            float diff = dot(s.Normal, lightDir);
            float3 reflectionVector = normalize(2.0 * s.Normal * diff - lightDir);

            // Calculate the Phong specular
            float spec = pow(max(0.0f, dot(reflectionVector, viewDir)), _SpecPower) * s.Specular;
            float3 finalSpec = s.SpecularColor * spec * _SpecularColor.rgb;

            // Create final color
            fixed4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb * diff) + (_LightColor0.rgb * finalSpec);
            c.a = s.Alpha;
            return c;
        }

        void surf(Input IN, inout SurfaceCustomOutput o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            float4 specMask = tex2D(_SpecularMask, IN.uv_SpecularMask) * _SpecularColor;

            o.Albedo = c.rgb;
            o.Specular = specMask.r;
            o.SpecularColor = specMask.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

五金与软高光

这一节,有点令人怕怕~
大家会用到的几张粗糙贴图:
图片 5
图片 6
图片 7
先上完整代码吧:

Shader "Custom/MetalAndSoftSpec" {
    Properties 
    {
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _RoughnessTex ("Roughness texture", 2D) = "" {}
        _Roughness ("Roughness", Range(0,1)) = 0.5
        _SpecularColor ("Specular Color", Color) = (1,1,1,1)
        _SpecPower ("Specular Power", Range(0,30)) = 2
        _Fresnel ("Fresnel Value", Range(0,1.0)) = 0.05
    }

    SubShader 
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf MetallicSoft
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _RoughnessTex;
        float _Roughness;
        float _Fresnel;
        float _SpecPower;
        float4 _MainTint;
        float4 _SpecularColor;

        inline fixed4 LightingMetallicSoft (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
        {
            //Compute simple diffuse and view direction values
            float3 halfVector = normalize(lightDir + viewDir);

            float4 c;
            //c.rgb = (s.Albedo * _LightColor0.rgb * halfVector);
            //return c;

            float NdotL = saturate(dot(s.Normal, normalize(lightDir)));
            //c.rgb = s.Albedo*_LightColor0.rgb * NdotL;
            //return c;

            float NdotH_raw = dot(s.Normal, halfVector);
            float NdotH = saturate(dot(s.Normal, halfVector));
            //c.rgb = s.Albedo*_LightColor0.rgb*NdotH;
            //return c;
            float NdotV = saturate(dot(s.Normal, normalize(viewDir)));
            float VdotH = saturate(dot(halfVector, normalize(viewDir)));
            //c.rgb = s.Albedo*_LightColor0.rgb*VdotH;
            //return c;

            //Micro facets distribution
            float geoEnum = 2.0*NdotH;
            float3 G1 = (geoEnum * NdotV)/NdotH;
            float3 G2 = (geoEnum * NdotL)/NdotH;
            float3 G =  min(1.0f, min(G1, G2));

            //Sample our Spceular look up BRDF
            float roughness = tex2D(_RoughnessTex, float2(NdotH_raw * 0.5 + 0.5, _Roughness)).r;

            //Create our custom fresnel value
            float fresnel = pow(1.0-VdotH, 5.0);
            fresnel *= (1.0 - _Fresnel);
            fresnel += _Fresnel;

            //Create the final spec
            float3 spec = float3(fresnel * G * roughness * roughness) * _SpecPower;

            //float4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb * NdotL)+  (spec * _SpecularColor.rgb) * (atten * 2.0f);
            c.a = s.Alpha;
            return c;
        }

        struct Input 
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

看了不怎么头晕,没事,听作者稳步说。

  1. _Roughness是粗糙度。用来支配高光的界定。越粗糙的实体高光范围越大,越光滑的物体高光越深远。漫反射的实体正是因为太粗糙了,高光范围大到看不见。

  2. _Fresnel是菲涅尔周详。当大家正对着物体时,物体高光就变得很弱,大约从不,比如正对水面包车型的士时候能够看见水底,侧着看的时候就能看见水面包车型客车波光。

  3. 让人头晕的正是光照函数了。里面注释掉的话语是本身的调剂,你们能够一层一层调节和测试看看。(聪明的儿女都友好上机调节和测试去了)

  4. halfVector是半角向量。G是几何衰减全面,描述由于微平面(microfacets)产生的自投影。G和半角之间的代码正是用来求G的。那个算法叫Cook–Torrance。看下Wiki:
    图片 8
    G的求法和代码中的求法是均等的。
    有关那几个算法的推理,搜索CookTorrance能够找到。比如那篇:http://www.twinklingstar.cn/2013/213/torrance-sparrow-and-cook-torrance-light-model/
    (小编承认,笔者看了一眼就放任了)

  5. 前边一句是从粗糙纹理的哈弗通道中收获粗糙度。因为粗糙贴图是黑白的,所以福特ExplorerGB八个通道的值都是均等的。NdotH_raw是原有的半角向量和法线的点积,乘0.5+0.5是为了让它的区间变成[0,1],因为纹理的坐标区间是[0,1],然后用粗糙度作为Y坐标,实行粗糙纹理的采集样品。

  6. 再前边是总结菲涅尔周密。菲涅尔周密的精神是反映被折射和反光的光通量的比率。那是菲涅尔周全的一个近乎求法。它的求法属于物艺术学的内容,那是近乎求法,精度在1%限量内。_Fresnel是大家在面板定义的四个变量。它是入射光接近0时(接近法线)的菲涅尔周详。关于它更详细的牵线,看那篇博文

  7. 说到底的反射变量就是菲涅尔周全乘几何衰减周详乘粗糙度的平方。最终的颜料卓殊漫反射颜色加镜面反射颜色。

骨子里Shader的就学是大学生阶段的教程,不过Unity让本科生也得以学一学。

金属与软高光

这一节,有点令人怕怕~
我们会用到的几张粗糙贴图:
图片 9
图片 10
图片 11
先上完整代码吧:

Shader "Custom/MetalAndSoftSpec" {
    Properties 
    {
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _RoughnessTex ("Roughness texture", 2D) = "" {}
        _Roughness ("Roughness", Range(0,1)) = 0.5
        _SpecularColor ("Specular Color", Color) = (1,1,1,1)
        _SpecPower ("Specular Power", Range(0,30)) = 2
        _Fresnel ("Fresnel Value", Range(0,1.0)) = 0.05
    }

    SubShader 
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf MetallicSoft
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _RoughnessTex;
        float _Roughness;
        float _Fresnel;
        float _SpecPower;
        float4 _MainTint;
        float4 _SpecularColor;

        inline fixed4 LightingMetallicSoft (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
        {
            //Compute simple diffuse and view direction values
            float3 halfVector = normalize(lightDir + viewDir);

            float4 c;
            //c.rgb = (s.Albedo * _LightColor0.rgb * halfVector);
            //return c;

            float NdotL = saturate(dot(s.Normal, normalize(lightDir)));
            //c.rgb = s.Albedo*_LightColor0.rgb * NdotL;
            //return c;

            float NdotH_raw = dot(s.Normal, halfVector);
            float NdotH = saturate(dot(s.Normal, halfVector));
            //c.rgb = s.Albedo*_LightColor0.rgb*NdotH;
            //return c;
            float NdotV = saturate(dot(s.Normal, normalize(viewDir)));
            float VdotH = saturate(dot(halfVector, normalize(viewDir)));
            //c.rgb = s.Albedo*_LightColor0.rgb*VdotH;
            //return c;

            //Micro facets distribution
            float geoEnum = 2.0*NdotH;
            float3 G1 = (geoEnum * NdotV)/NdotH;
            float3 G2 = (geoEnum * NdotL)/NdotH;
            float3 G =  min(1.0f, min(G1, G2));

            //Sample our Spceular look up BRDF
            float roughness = tex2D(_RoughnessTex, float2(NdotH_raw * 0.5 + 0.5, _Roughness)).r;

            //Create our custom fresnel value
            float fresnel = pow(1.0-VdotH, 5.0);
            fresnel *= (1.0 - _Fresnel);
            fresnel += _Fresnel;

            //Create the final spec
            float3 spec = float3(fresnel * G * roughness * roughness) * _SpecPower;

            //float4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb * NdotL)+  (spec * _SpecularColor.rgb) * (atten * 2.0f);
            c.a = s.Alpha;
            return c;
        }

        struct Input 
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

看了不怎么头晕,没事,听本身慢慢说。

  1. _Roughness是粗糙度。用来决定高光的界定。越粗糙的物体高光范围越大,越光滑的实体高光越浓密。漫反射的物体正是因为太粗糙了,高光范围大到看不见。

  2. _Fresnel是菲涅尔全面。当大家正对着物体时,物体高光就变得很弱,差不多从未,比如正对水面包车型的士时候能够望见水底,侧着看的时候就能瞥见水面包车型客车波光。

  3. 令人头晕的便是光照函数了。里面注释掉的语句是本身的调节,你们能够一层一层调试看看。(聪明的孩子都要好上机调节和测试去了)

  4. halfVector是半角向量。G是几何衰减全面,描述由于微平面(microfacets)发生的自投影。G和半角之间的代码便是用来求G的。那几个算法叫库克–Torrance。看下Wiki:
    图片 12
    G的求法和代码中的求法是相同的。
    至于那个算法的演绎,搜索CookTorrance能够找到。比如那篇:http://www.twinklingstar.cn/2013/213/torrance-sparrow-and-cook-torrance-light-model/
    (我承认,笔者看了一眼就甩掉了)

  5. 背后一句是从粗糙纹理的奥迪Q3通道中拿走粗糙度。因为粗糙贴图是黑白的,所以宝马7系GB四个通道的值都以均等的。NdotH_raw是原有的半角向量和法线的点积,乘0.5+0.5是为了让它的距离变成[0,1],因为纹理的坐标区间是[0,1],然后用粗糙度作为Y坐标,进行粗糙纹理的采集样品。

  6. 再后面是计算菲涅尔周密。菲涅尔周详的原形是反映被折射和反光的光通量的比率。那是菲涅尔周详的1个接近求法。它的求法属于物艺术学的内容,那是接近求法,精度在1%限量内。_Fresnel是我们在面板定义的2个变量。它是入射光接近0时(接近法线)的菲涅尔周详。关于它更详尽的介绍,看那篇博文

  7. 末段的反射变量正是菲涅尔周详乘几何衰减周到乘粗糙度的平方。最后的颜料相当漫反射颜色加镜面反射颜色。

实际Shader的就学是大学生阶段的教程,不过Unity让本科生也足以学一学。