zoukankan      html  css  js  c++  java
  • 【转】Phong和Blinn-Phong光照模型

    来自:http://www.cnblogs.com/bluebean/p/5299358.html

    Phong和Blinn-Phong是计算镜面反射光的两种光照模型,两者仅仅有很小的不同之处。

     

    1.Phong模型

    Phone模型计算中的一个关键步骤就是反射向量R的计算:

     

    上图中的位于表面“下面”的向量 ‘I’ 是原始 ‘I’ 向量的拷贝,并且二者是一样的,现在我们的目标计算出向量 ‘R’ 。根据向量相加原则,向量 ‘R’ 等于 'I' + 'V',‘I’ 是已知的,所以我们需要做的就是找出向量 ‘V’。注意法向量 ‘N’ 的负方向就是 ‘-N’,我们可以在 ‘I’ 和 ‘-N’ 之间使用一个点乘运算就能得到 ‘I’ 在 ‘-N’ 上面的投影的模。这个模正好是 ‘V’ 的模的一半,由于 ‘V’ 与 ‘N’ 有相同的方向,我们可以将这个模乘上 ‘N’ (其模为 1 )再乘上 2 即可得到 ‘V’。总结一下就是下面的公式:

     

    2.Blinn-Phong模型

     Phong模型中计算反射光线的向量是一件相对比较耗时的任务,因此Blinn-Phong对这一点进行了改进。

     

    Ks:物体对于反射光线的衰减系数

    N:表面法向量

    H:光入射方向L和视点方向V的中间向量

    Shininess:高光系数

    可见,通过该式计算镜面反射光是符合基本规律的,当视点方向和反射光线方向一致时,计算得到的H与N平行,dot(N,H)取得最大;当视点方向V偏离反射方向时,H也偏离N。

    同时H的计算比起反射向量R的计算简单的多,R向量的计算需要若干次的向量乘法与加法,而H的计算仅仅需要一次加法。

    下面是用cg着色语言书写的Phong和Blinn-Phong的顶点和片段着色程序

    Phong_FragmentLighting_v.cg
    复制代码
     1 struct V2F{
     2     float4 position:POSITION;
     3     float3 worldPosition: TEXCOORD0;
     4     float3 worldNormal :TEXCOORD1;
     5 };
     6 void Phong_FragmentLighting_v(float4 position :POSITION,
     7                               float4 normal:NORMAL,
     8                               uniform float4x4 modelMatrix,
     9                               uniform float4x4 modelMatrix_IT,
    10                               uniform float4x4 modelViewProj,
    11                               out V2F O){
    12     O.position=mul(modelViewProj,position);
    13     O.worldPosition=mul(modelMatrix,position).xyz;
    14     O.worldNormal=normalize(mul(modelMatrix_IT,normal)).xyz;
    15 }
    复制代码
    Phong_FragmentLighting_f.cg
    复制代码
     1 void Phong_FragmentLighting_f(float3 position :TEXCOORD0,
     2                                float3 normal: TEXCOORD1,
     3                                uniform float3 globalAmbient,
     4                                uniform float3 lightColor,
     5                                uniform float3 lightPosition,
     6                                uniform float3 eyePosition,
     7                                uniform float3 Ke,
     8                                uniform float3 Ka,
     9                                uniform float3 Kd,
    10                                uniform float3 Ks,
    11                                uniform float  shininess,
    12                                out float4 color:COLOR)
    13               {
    14                   float3 N=normalize(normal);
    15                   float3 L=normalize(lightPosition-position);     
    16                   float3 V=normalize(eyePosition-position);
    17                   
    18                   float3 R=reflect(-L,N);
    19                   R=normalize(R);
    20                   
    21                   // Compute emissive term
    22                   float3 emissive = Ke;
    23 
    24                  // Compute ambient term
    25                  float3 ambient = Ka * globalAmbient;
    26 
    27                 // Compute the diffuse term
    28                 float diffuseLight = max(dot(N, L), 0);
    29                 float3 diffuse = Kd * lightColor * diffuseLight;
    30 
    31                 // Compute the specular term
    32                 float specularLight = pow(max(dot(V, R), 0), shininess);
    33                 if (diffuseLight <= 0) specularLight = 0;
    34                 float3 specular = Ks * lightColor * specularLight;
    35 
    36                 //color.xyz = emissive + ambient + diffuse + specular;
    37                 color.xyz=ambient + diffuse + specular;
    38                 color.w = 1;
    39               }
    复制代码
    BlinnPhong_FragmentLighting_v.cg
    复制代码
     1 struct V2F{
     2     float4 position:POSITION;
     3     float3 worldPosition: TEXCOORD0;
     4     float3 worldNormal :TEXCOORD1;
     5 };
     6 void BlinnPhong_FragmentLighting_v(float4 position :POSITION,
     7                               float4 normal:NORMAL,
     8                               uniform float4x4 modelMatrix,
     9                               uniform float4x4 modelMatrix_IT,
    10                               uniform float4x4 modelViewProj,
    11                               out V2F O){
    12     O.position=mul(modelViewProj,position);
    13     O.worldPosition=mul(modelMatrix,position).xyz;
    14     O.worldNormal=normalize(mul(modelMatrix_IT,normal)).xyz;
    15 }
    复制代码
     
    BlinnPhong_FragmentLighting_f.cg
    复制代码
     1 void BlinnPhong_FragmentLighting_f(float3 position :TEXCOORD0,
     2                                float3 normal: TEXCOORD1,
     3                                uniform float3 globalAmbient,
     4                                uniform float3 lightColor,
     5                                uniform float3 lightPosition,
     6                                uniform float3 eyePosition,
     7                                uniform float3 Ke,
     8                                uniform float3 Ka,
     9                                uniform float3 Kd,
    10                                uniform float3 Ks,
    11                                uniform float  shininess,
    12                                out float4 color:COLOR)
    13               {
    14                   float3 N=normalize(normal);
    15                   float3 L=normalize(lightPosition-position);     
    16                   float3 V=normalize(eyePosition-position);
    17                   
    18                  float3 H=normalize(L+V);
    19                   
    20                   // Compute emissive term
    21                   float3 emissive = Ke;
    22 
    23                  // Compute ambient term
    24                  float3 ambient = Ka * globalAmbient;
    25 
    26                 // Compute the diffuse term
    27                 float diffuseLight = max(dot(N, L), 0);
    28                 float3 diffuse = Kd * lightColor * diffuseLight;
    29 
    30                 // Compute the specular term
    31                 float specularLight = pow(max(dot(H, N), 0), shininess);
    32                 if (diffuseLight <= 0) specularLight = 0;
    33                 float3 specular = Ks * lightColor * specularLight;
    34 
    35                 color.xyz=ambient + diffuse + specular;
    36                 color.w = 1;
    37               }
    复制代码

    效果对比:


    Phong光照模型


    Blinn-Phong光照模型

    通过简单的对比发现,在相同条件下Blinn-Phong的高光范围要比Phong更大,写实效果Phong光照模型更好。但算法简单,运行速度快是Blinn-Phong光照模型的优点。
  • 相关阅读:
    android闹钟
    Android API : SMS短信服务处理
    Windows Mobile Web方式下载文件
    摘录的一点东西,很有感触
    Net Compact Framework 基础篇(6) Socket通信 【转】
    实例讲解.NET中资源文件的创建与使用
    如何安装Apk文件到Android模拟器
    __forceinline 关键字
    Allocate aligned memory
    linux svn安装和配置,不结合apache
  • 原文地址:https://www.cnblogs.com/timeObjserver/p/9473750.html
Copyright © 2011-2022 走看看