Unity Shader - 高光反射(Phong、Blinn-Phong)

高光反射光照模型分为Phong模型Blinn-Phong模型:

Phong 模型公式:

高光反射 = 光源颜色 * 反射颜色 ∗ pow( max(0, 视角v与光反射向量r的余弦值) , 光泽度)

如下图:

Blinn-Phong 模型公式:

高光反射 = 光源颜色 * 反射颜色 ∗ pow( max(0, 半角向量h与法线n的余弦值) , 光泽度)

如下图:

 逐顶点高光反射:

Shader "Unlit/003"
{
    Properties
    {
        _Specular ("_Specular",Color) = (1,1,1,1)
        // 高光反射值
        _Gloss ("_Gloss",range(1,100)) = 5
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            float4 _Specular;
            half _Gloss;
            
            struct v2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : POSITION;
                float3 color : Color;
            };

            v2f vert (v2v v)
            {
                v2f o;
                // 将对象空间中的点变换到齐次坐标中的摄像机裁剪空间
                o.vertex = UnityObjectToClipPos(v.vertex);
                // 光源方向
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                // 将法向量转到世界坐标法向量
                float3 normal = UnityObjectToWorldNormal(v.normal);

                // 视野方向
                float3 viewDir = normalize(_WorldSpaceCameraPos.xyz- UnityObjectToWorldDir(v.vertex));
                // 反射方向
                float3 reflectDir = normalize(mul(normal,2) - lightDir);
                // float3 reflectDir = normalize(reflect(-lightDir,normal));
                
                // Phong 模型公式高光反射计算
                float3 specular = _LightColor0.rab * _Specular.rgb * pow(max(0,dot(reflectDir,viewDir)),_Gloss);
          
                // 半角向量
                float3 _half = normalize(mul(lightDir + viewDir,0.5));      
                // Blinn-Phong 模型公式高光反射计算
                //float3 specular = _LightColor0.rab * _Specular.rgb * pow(max(0,dot(_half,normal)),_Gloss);   
                
                o.color = specular;
                return o;   
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float4 color = float4(i.color,1);
                return color;
            }
            ENDCG
        }
    }
}

逐片元:

Shader "Unlit/004"
{
    Properties
    {
        _Specular ("_Specular",Color) = (1,1,1,1)
        // 高光反射值
        _Gloss ("_Gloss",range(1,256)) = 5
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            float4 _Specular;
            half _Gloss;
            
            struct v2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : POSITION;
                float3 normal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
            };

            v2f vert (v2v v)
            {
                v2f o;
                // 将对象空间中的点变换到齐次坐标中的摄像机裁剪空间
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.normal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = UnityObjectToWorldDir(v.vertex);
                return o;   
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
                float3 reflectDir = normalize(mul(i.normal , 2) - _WorldSpaceLightPos0.xyz);
                // Phong 模型公式高光反射计算
                float3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(reflectDir,viewDir)),_Gloss);
                
                // 半角向量
                float3 _half = normalize(mul(normalize(_WorldSpaceLightPos0.xyz) + viewDir,0.5));      
                // Blinn-Phong 模型公式高光反射计算
                //float3 specular = _LightColor0.rab * _Specular.rgb * pow(max(0,dot(_half,i.normal)),_Gloss);   
                
                return float4(specular,1);
            }
            ENDCG
        }
    }
}

看下效果 左边是逐顶点,右边是逐片源

phong 模型:

 Blinn-Phong 模型:

 可以看到逐顶点渲染和逐像素渲染的区别:逐片元更加细腻

猜你喜欢

转载自blog.csdn.net/weixin_41316824/article/details/131156054