Blinn-Phong & Phong

(23.3.16 Pick up knowledge again today, start reviewing from phong)

reference:
learn opengl
"Introduction to unityshader"



structure

Note that all the formulas in this article are light intensity and cannot be directly used in the shader, because the calculation of the reflected color is also required

In order to remember better, combine the two types of lighting to contrast and remember that


   phong lighting consists of three parts, as shown in the figure

insert image description here


Ambient ambient light

slightly

Diffuse diffuse light

Diffuse lighting is not view-line dependent, only light and surface normal, so the result is like a map

The role of diffuse reflection is only to calculate the weakening light intensity according to the angle of incidence, nothing more:
insert image description here

C = −L ⋅ NC = -L NC=LN
L is the light vector, N is the normal vector

diff = max(dot(norm, lightDir), 0.0)
(The max function limits the dot product to [0, 1], and it cannot be illuminated if it is greater than 90 degrees, and it also avoids negative numbers)

That is, the diffuse intensity is proportional to the cosine of LN

Specular highlights

Wind

Highlights are only related to two vectors: the line of sight direction and the reflection direction (but the reflection vector is also calculated)

insert image description here
As shown in the figure, it seems that there are many vectors, but only two are really needed, V and R, but in order to achieve a bright spot (a small block), we need an exponential operation:

C = ( V ⋅ R ) g C = (V·R)^{g} C=(VR)g

  • V is the line of sight vector, R is the reflection vector, g is the gloss coefficient gloss/shininess (the bigger the more concentrated)
  • In fact, this formula is also the highlight distribution of phong. When the roughness g is 1, its attenuation curve is a cos function [ 0 , π 2 ) [0,\frac{\pi}{2})[0,2p) part; then the difference in g can change the shape of the distribution, the smaller the g, the smoother the distribution, and the larger the steeper (power function)
  • Since there is no energy conservation in PBR, when g is relatively small, the highlights will look too big and too bright
  • The distribution of specular and diffuse with g=1 is different! Although they are all Gaussian distributions, they work in different ways. Diffuse is a directional light, and spec is a point light source.

spec = pow(max(dot(viewDir, reflectDir), 0.0), gloss)
(The purpose of the max function is to limit the dot product to [0, 1], avoiding the occurrence of negative numbers, but unfortunately, the direction of sight and reflection can be greater than 90 degrees, which is also the defect of phong)

R can be calculated by a special function reflect(N, -L) (whether this is specific has not yet been verified), the specific formula seems to be very troublesome, and will be added later


Blinn-Phong

bp no longer needs to calculate the reflection vector, and there
are only two vectors related to the half-way vector: normal, half-way vector (need to be calculated)
insert image description here

C = ( H ⋅ N ) g C=(H·N)^g C=(HN)g
spec = pow(max(dot(halfDir,normal), 0.0), gloss)
(No matter how H changes, it will not be greater than 90 degrees, so the max here is completely fine, and the calculation of H is easier than R)
halfDir = normalize(lightDir + viewDir)




Comparison of the advantages and disadvantages of the two

Problems with phong

When the gloss is too small, the highlight area will be very large, which is not a problem in itself, but it will form a highlight fault at certain angles (usually looking at the ground along the light):

insert image description here

Reason: When we apply phong's highlight calculation, we will define the part of sight V and reflection R greater than 90 degrees as 0, which is to prevent negative numbers from appearing ( cos 12 0 ∘ = − 0.5 cos120^\circ = -0.5cos120=0.5 ), but in reality, the angle of V and R may be greater than 90 degrees:
insert image description here
this leads to a fault, because the highlights greater than 90 degrees disappear directly,
so blinn-phong is commonly used:
insert image description here


Both effects

Because both are empirical models, there are no advantages or disadvantages in terms of effect.
The only difference between the two is the calculation of highlights, so the difference in effect is only the highlight part: the
insert image description here
included angle of blinnphong is usually smaller than the included angle of phong, Therefore, when the highlight area is similar, the gloss of phong' will be much smaller;
even if the area is the same, the specular light of glossBlinn-Phong will be sharper than the Phong model

running speed

Generally speaking, blinn will be faster, (in terms of hardware implementation, which one is faster, R or H, has not yet been verified)

(Getting started: When the camera and the light source are far enough away from the model , blinn-phong will be faster, because H will be treated as a constant in hardware processing; when it is too close to be regarded as a constant, phong may be faster) Personally not
very Agree and understand: GPU will be optimized for this kind of thing? Also treated as a constant according to the distance, a bit exaggerated)

The problem of coexistence

1. Fresnel cannot be calculated (the empirical model will not be used in PBR)
2. Anisotropy (such as metal wire drawing) cannot be calculated (still not available)
  because it is isotropic, fixed camera and Light source, the light will not change when the surface of the object rotates, but the anisotropic surface will change




Unity shader implementation

Shader "Unlit/phong"
{
    
    
    Properties
    {
    
    
        _Diffuse ("Diffuse", Color) = (1,1,1,1)
        _Specular ("Specular", Color) = (1,1,1,1)
        _Gloss ("Gloss", Range(8,256)) = 20
    }
    SubShader
    {
    
    
        Pass
        {
    
    
            Tags {
    
    "LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include "UnityCG.cginc"
            #include "Lighting.cginc" //导入这个包是为了使用外源环境光_LightColor0,否则只能使用自己指定的环境光,可能会不自然

            struct appdata
            {
    
    
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
    
    
                float4 vertex : SV_POSITION;
                float3 w_Normal : TEXCOORD0;
                float3 w_Pos : TEXCOORD1;
            };

            float4 _Diffuse;
            float4 _Specular;
            float _Gloss;

            v2f vert (appdata v)
            {
    
    
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);

                o.w_Normal = UnityObjectToWorldDir(v.normal); //注意这两句的两种不同实现方法
                o.w_Pos = mul(unity_ObjectToWorld, v.vertex).xyz;

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
    
    
                float3 w_Normal = normalize(i.w_Normal);
                float3 w_LightDir = normalize(_WorldSpaceLightPos0.xyz);
                float3 reflectDir = normalize(reflect(-w_LightDir,w_Normal));
                float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.w_Pos.xyz);
 
                float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                float3 diff = _LightColor0.rgb * _Diffuse.rgb * max(dot(w_Normal, w_LightDir), 0.0);
                float3 spec = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);

                return fixed4(ambient + diff + spec , 1.0);
            }
            ENDCG
        }
    }
}

Guess you like

Origin blog.csdn.net/dogman_/article/details/129586395