Blinn-Phong 光照模型

本文详细介绍了Blinn-Phong光照模型,对比Phong模型,该模型通过引入新的矢量h,计算高光反射,使得高光效果更自然,更符合实验结果。文中还提供了Shader代码实例。

前面 我们使用Phong光照模型计算的高光反射,这里我们 用Blinn-Phong来实现高光反射计算。

在Blinn-Phong中,没有使用反射方向,而是引入了新的矢量h,它是通过对视角方向v 和光照方向 l 相加后再归一化得到的。

\hat{h}=(\hat{v}+\hat{l})/(l\hat{v}+\hat{l}l)

所以Blinn-Phong 模型计算高光反射公式如下:

_{Cspecular}=(_{Clight} * _{Mspecular})max(0,\hat{n}\cdot\hat{h})^{_{Mgloss}}

计算如下:

Shader "Custom/SpecularBlinnPhong"
{
    Properties
    {
        _DiffuseColor("DiffuseColor",Color)=(1,1,1,1)
        _SpecularColor("SpecularColor",Color)=(1,1,1,1)
        _Gloss("Gloss",Range(8,256))=20
    }

    SubShader
    {
        pass
        {
            Tags{"LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            fixed4 _DiffuseColor;
            fixed4 _SpecularColor;
            float _Gloss;


            struct a2v
            {
                float4 vertPos:POSITION;
                float3 normal:NORMAL;

            };

            struct v2f
            {
                float4 pos:SV_POSITION;
                float3 worldNormal:TEXCOORD0;
                float3 worldPos:TEXCOORD1;
            };

            v2f vert(a2v v)
            {
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertPos);
                o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
                o.worldPos=mul(unity_ObjectToWorld,v.vertPos).xyz;
                return o;
            }

            fixed4 frag(v2f i):SV_Target
            {
                fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
                fixed3 worldNormal=normalize(i.worldNormal);
                fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
                fixed3 diffuse=_LightColor0.rgb*_DiffuseColor.rgb*saturate(dot(worldNormal,worldLightDir));
                fixed3 reflectDir=normalize(reflect(-worldLightDir,worldNormal));
                fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
                fixed3 halfDir=normalize(worldLightDir+viewDir);
                fixed3 specular=_LightColor0.rgb*_SpecularColor.rgb*pow(max(0,dot(worldNormal,halfDir)),_Gloss);
                fixed3 scolor=ambient+diffuse+specular;
                return fixed4(scolor,1);
            }

            ENDCG
        }

    }
    FallBack "Diffuse"
}

效果如下:右边是Blinn-Phong光照模型实现的高光反射,左边是Phong模型实现的。

Blinn-Phong 实现的高光更大,更亮。这两种模型都是经验模型。实际上Blinn-Phong模型 更符合实验结果。

Blinn - Phong光照模型是在Phong光照模型基础上的改进,它引入了半程向量来替代反射向量,从而减少了计算量。下面是一个简单的GLSL代码示例来实现Blinn - Phong光照模型用于茶壶的渲染: ```glsl // 顶点着色器 #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; out vec3 FragPos; out vec3 Normal; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { FragPos = vec3(model * vec4(aPos, 1.0)); Normal = mat3(transpose(inverse(model))) * aNormal; gl_Position = projection * view * vec4(FragPos, 1.0); } // 片段着色器 #version 330 core out vec4 FragColor; in vec3 FragPos; in vec3 Normal; uniform vec3 lightPos; uniform vec3 viewPos; uniform vec3 lightColor; uniform vec3 objectColor; void main() { // 环境光 float ambientStrength = 0.1; vec3 ambient = ambientStrength * lightColor; // 漫反射 vec3 norm = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * lightColor; // Blinn-Phong镜面反射 float specularStrength = 0.5; vec3 viewDir = normalize(viewPos - FragPos); vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(norm, halfwayDir), 0.0), 32); vec3 specular = specularStrength * spec * lightColor; vec3 result = (ambient + diffuse + specular) * objectColor; FragColor = vec4(result, 1.0); } ``` 上述代码分为顶点着色器和片段着色器两部分。顶点着色器负责处理顶点的位置和法线变换,而片段着色器实现了Blinn - Phong光照模型的具体计算,包括环境光、漫反射和镜面反射
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值