• 热门专题

Directx11教程(22) 简单的光照模型(1)

作者:迈克老狼2012  发布日期:2012-04-10 11:35:55
Tag标签:Directx11  光照模型  
  •      在前面的例子中,我们在顶点属性中直接给顶点赋颜色值,这样生成的三维物体缺乏真实感,如下图中两个立方体,左边的是通过光照生成物体表面颜色的,右边的则是直接给顶点赋颜色值。

    image

        

    本章中,我们将学习最简单的phong光照模型:

     

          在phong光照模型中,物体表面的颜色由自发射光(emissive)、环境光(ambient)、漫反射光(diffuse)以及镜面高光(specular)四部分组成,每一部分又是通过物体表面的材质属性和光照属性一起来决定。用公式来表示就是:

     

         surfaceColor = emissive + ambient + diffuse + specular

     

    自发射光(emissive):

    image

         这表示物体本身具有发射光的属性,它是独立于光源的,同时她它本身也不是光源,不会对场景中的其它为物体有影响。通常emissive用一个常量颜色来表示。

         emissive = Ke, Ke表示材质的自发射光属性。

     

    环境光(ambient):

    image

          环境光模拟场景中来自于来自于各个方向的光线,这些光线也没有位置的概念,比如白天我们在房间里,没有任何特定光源,但我们房间确实亮的。通常它等于

          ambient = Ka x globalAmbient

          Ka表示材质的环境光反射系数,globalAmbient表示入射光线的环境光系数,它们通常都是2个颜色常量。

     

    漫反射光(diffuse):

     

    image

          漫反射光通常指方向光在物体表面不同方向的反射光,如上图所示,在粗糙的表面上,入射光的反射投向不同的方向。反射光的计算通常用Lambert定律:

     

    diffuse = Kd x lightColor x max(N · L, 0)

     

    • Kd  是材质的漫反射颜色系数, lightColor 是入射光的颜色
    • N  是物体表面的法向
    • L  是光源到顶点的归一化向量
    • P  是着色的顶点位置

    image

    高光(specular):

     

         在光滑的表面,比如金属球,通常有高光的效果。高光通常是物体光滑表面的镜面反射散射效果。

    image

          高光和光源方向和视点都有关系,它的计算公式如下:

    specular = Ks x lightColor x facing x (max(N · H, 0)) shininess

    where:

    • Ks 是材质的高光系数, lightColor是光源颜色
    • N 是归一化的物体表面法向
    • V 是归一化的视点向量
    • L 是归一化的光源方向向量
    • H 等于归一化的向量(V+L)/2
    • P 是着色的顶点位置
    • 如果N · L > 0facing 是 1 ,否则是0image

     

    了解的基本的光照模型以后,我们开始光照程序的编写:

     

          首先,新建一个CubeModelClass类,该类表示一个cube立方体,但和ModelClass类不同的是,在顶点结构中我们去掉了color属性,增加了normal属性。

    struct VertexType
        {
        D3DXVECTOR3 position;
        D3DXVECTOR3 normal; //法向
        };

         该立方体中心在原点,每个顶点的法向,我都取原点到该顶点位置的归一化向量(在shader中实现归一化,给顶点法向赋值是,我并没有做归一化操作)。每个顶点法向位置大概如下图红色线段所示:

    image

     

         接下来,我们要定义两个新的shader文件light.vs和light.ps,新的基于材质和光源的物体渲染,将使用这两个文件。这两个文件的中光照计算公司就是利用上面的讲的phong光照管理。

     

        surfaceColor = emissive + ambient + diffuse + specular

        我们在light.vs中实现光照计算,需要注意的是,在利用漫反射(高光)时候,我用了方向光(directional light,所有光线都是一个方向,比如无穷远处的光源,类似太阳光),代码大致如下:

        //自发射颜色
        float3 emissive = float3(0.0, 0.0, 0.0);
       
        //计算环境光
        float3 ambient =  float3(0.3, 0.3, 0.3);
       
        //计算漫反射光
         float3 L = normalize(float3(-1.0, -1.0, 1.0));
         float diffuseLight = max(dot(N, L), 0);
         float3 diffuse =  diffuseLight;

         //计算高光
         float3 V = normalize(cameraPosition - P);
         float3 H = normalize(L + V);
         float specularLight = pow(max(dot(N, H), 0), 5.0);
     
          if (diffuseLight <= 0)
              specularLight = 0;
          float3 specular =  specularLight;

          output.color.xyz = emissive + ambient + diffuse + specular;

     

          接下来,我们又定义LightShaderClass类,主要用该类实现light.vs和light.ps的载入,参数初始化以及执行shader等功能。

         最后就是在GraphicsClass中创建LightShaderClass和CubeModelClass类,渲染这个新的cube对象(老的modelClass也是一个cube,但我们用colorShader渲染它,并且它的位置也被挪到右边)。

     

         程序运行后的界面如下:

    image

    完整的代码请参考:

    工程文件myTutorialD3D11_15

    代码下载:


     http://down1.it165.net/pro/201204/0401myTutorialD3D11.zip

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规