原文:Directx教程(28) 简单的光照模型(7)

       现实生活中的点光源都是随着距离衰减的,比如一个电灯泡在近处会照的很亮,远处光线就很弱。本节中我们在前面光公式的基础上,再给漫反射和高光加上一个衰减因子。

      光源随着距离衰减并不是纯线性的,常用的公式是:

  • d 是光源到着色点的距离。
  • kC, kL, 和 kQ 分别是常量、线性以及二次衰减系数。

现在在light.ps中,计算光照的代码变成了:

  for ( i = 0; i < NUM_LIGHTS; i++)
  {
    //自发射颜色
    emissive = Ke[i];
   
   //计算环境光
    ambient = Ka[i] * globalAmbient[i];
   
    //计算漫反射光
    //用LightDirection就是纯平行光
    //光源位置减顶点位置
     L = normalize(lightPosition[i].xyz - P);
     d = distance(lightPosition[i].xyz, P);
     //衰减系数
     atte = 1 / (attenuation[i].x + attenuation[i].y * d +attenuation[i].z * d * d);
     diffuseLight = max(dot(N, L), 0);
     diffuse =   Kd[i] * lightColor[i] * diffuseLight * atte ;

     //计算高光
     V = normalize(cameraPosition.xyz - P);
     H = normalize(L + V);
     specularLight = pow(max(dot(N, H), 0), shininess[i]);
 
      if (diffuseLight <= 0)
          specularLight = 0;
      specular = Ks[i] * lightColor[i] * specularLight *  atte;

      finalcolor +=  emissive + ambient + diffuse + specular;
     }

   

     相应的,在lightShaderClass.h中的struct  LightMaterialBufferType,也要做一些变化,增加一个D3DXVECTOR4分量attenuation,它的x,y,z分别表示常量、线性以及二次衰减系数。之所以用D3DVECTOR4,是因为const buffer要求是4的倍数,我曾尝试用3个float,结果程序竟然有编译错误。

D3DXVECTOR4 attenuation[NUM_LIGHTS]; //衰减系数,x,y,z对应常量,线性和二次系数

    在light.ps中,const buffer  LightMaterialBuffer,也要增加衰减因子,它和LightMaterialBufferType中的attenuation是相对应的。

float4 attenuation[NUM_LIGHTS]; //衰减系数

 

程序执行后的效果如下:

完整的代码请参考:

工程文件myTutorialD3D11_21

代码下载:

http://files.cnblogs.com/mikewolf2002/myTutorialD3D11.zip

    接下来我们再实现一个探照灯(spotlight)的效果,如下图所示,只有在圆锥内角(inner)的范围才是光照能够达到的范围。但是只考虑内角的话,我们的光照会比较生硬,内角圆锥内,有光,内角圆锥外,一片漆黑,所以我们又加了一个外角(outer),对于内角和外角之间的空间,我们使用hlsl的差值函数smoothstep来计算得到一个0-1之间的数值。

 

 

 

light.ps的主要代码:

    下面的函数通过smoothstep计算出spotlight的因子。其中cosInnerCone是内角的余弦值,cosOuterCone是外角的余弦值。如果计算出的cosDirection值大于内角余弦值,则smoothstep值为1,如果cosDirection值小于外角余弦值,则其值为0,对于在这两者之间的值,smoothstep会用多项式差值得到一个0-1之间的值。

//一个计算spot light系数的函数
float dualConeSpotlight(float3 P, float3 lightpos, float3 lightdir, float  cosInnerCone, float cosOuterCone)
{
 
  float3 V = normalize(P - lightpos);
 
  float cosDirection = dot(V, normalize(lightdir));
 
  return smoothstep(cosOuterCone,  cosInnerCone, cosDirection);
}

  for ( i = 0; i < NUM_LIGHTS; i++)
  {
       //自发射颜色
    emissive = Ke[i];
   
    //计算环境光
    ambient = Ka[i] * globalAmbient[i];
   
    //计算漫反射光
    //用LightDirection就是纯平行光,在spotlight情况下代表光的方向

    spotEffect = dualConeSpotlight(P,  lightPosition[i].xyz, lightDirection[i],spotattenuation[i].x, spotattenuation[i].y);

    //光源位置减顶点位置
     L = normalize(lightPosition[i].xyz - P);
     d = distance(lightPosition[i].xyz, P);
     //衰减系数
     atte = 1 / (attenuation[i].x + attenuation[i].y * d +attenuation[i].z * d * d);
     diffuseLight = max(dot(N, L), 0);
     diffuse =   Kd[i] * lightColor[i] * diffuseLight * atte * spotEffect;

     //计算高光
     V = normalize(cameraPosition.xyz - P);
     H = normalize(L + V);
     specularLight = pow(max(dot(N, H), 0), shininess[i]);
 
      if (diffuseLight <= 0)
          specularLight = 0;
      specular = Ks[i] * lightColor[i] * specularLight * spotEffect;

      finalcolor +=  emissive + ambient + diffuse + specular;
     }

     同样的,我们的const buffer LightMaterialBuffer中,增加了

         float4 spotattenuation[NUM_LIGHTS];

     它的x,y分别表示内角和外角余弦值。

     lightShaderClass.h中的材质光照结构中也增加了

        D3DXVECTOR4 spotattenuation[NUM_LIGHTS]; //对于spotlight,x,y分别存储内和外角cos值

程序最终执行效果如下:

 

完整的代码请参考:

工程文件myTutorialD3D11_22

代码下载:

http://files.cnblogs.com/mikewolf2002/myTutorialD3D11.zip

Directx教程(28) 简单的光照模型(7)的更多相关文章

  1. Directx教程(29) 简单的光照模型(8)

    原文:Directx教程(29) 简单的光照模型(8)      现在我们新建一个工程myTutorialD3D_23,在这个工程中,对前面一章的代码进行一些整理: 1.我们在顶点属性中增加材质的的漫 ...

  2. Directx教程(27) 简单的光照模型(6)

    原文:Directx教程(27) 简单的光照模型(6)      从myTutorialD3D11_15到myTutorialD3D11_19的工程中,我们都只有一个光源,光源的位置在LightCla ...

  3. Directx教程(26) 简单的光照模型(5)

    原文:Directx教程(26) 简单的光照模型(5)     在前面的工程中,我们都是在vs中实现顶点光照计算,然后再把顶点颜色传到ps中.本章中我们尝试fragment光照(或者说叫ps光照),在 ...

  4. Directx教程(25) 简单的光照模型(4)

    原文:Directx教程(25) 简单的光照模型(4)      在本篇日志中,我们尝试用不带衰减的点光源来计算漫反射颜色.     前面的三个工程,我们都用的是方向光源(directional li ...

  5. Directx教程(24) 简单的光照模型(3)

    原文:Directx教程(24) 简单的光照模型(3)      在工程myTutorialD3D11_17中,我们重新定义我们的cube顶点法向,每个三角形面的顶点法向都是和这个三角形的面法向是一致 ...

  6. Directx教程(23) 简单的光照模型(2)

    原文:Directx教程(23) 简单的光照模型(2)    在工程myTutorialD3D11_16中,我在文件light.vs中定义了一个材质光源属性常量缓冲. //const buffer最好 ...

  7. Directx教程(22) 简单的光照模型(1)

    原文:Directx教程(22) 简单的光照模型(1)      在前面的教程中,我们在顶点属性中直接给顶点赋颜色,这样生成的三维物体缺乏真实感,如下图中两个立方体,左边的是通过光照生成物体表面颜色的 ...

  8. 【Visual C++】游戏开发五十六 浅墨DirectX教程二十三 打造游戏GUI界面(一)

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/16384009 作者:毛星云 ...

  9. [译]Vulkan教程(28)Image视图和采样器

    [译]Vulkan教程(28)Image视图和采样器 Image view and sampler - Image视图和采样器 In this chapter we're going to creat ...

随机推荐

  1. 左神算法书籍《程序员代码面试指南》——2_02在单链表和双链表中删除倒数第k个字节

    [题目]分别实现两个函数,一个可以删除单链表中倒数第K个节点,另一个可以删除双链表中倒数第K个节点.[要求]如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1).[题解]从头遍历链表, ...

  2. ArrayList基础知识

    ArrayList简介 ArrayList 的底层是数组队列,相当于动态数组.与 Java 中的数组相比,它的容量能动态增长.在添加大量元素前,应用程序可以使用ensureCapacity操作来增加 ...

  3. 高斯消元和高斯约旦消元 Gauss(-Jordan) Elimination

    高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵. 在讲算法前先介绍些概念 矩阵的初等变换 矩阵的初等变换又分为矩阵的初等行变换和矩阵的初等列变换 ...

  4. Leetcode220. Contains Duplicate III存在重复元素3

    给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. 示例 1: 输入: ...

  5. MySQL系列(八)--数据库分库分表

    在互联网公司或者一些并发量比较大的项目,虽然有各种项目架构设计.NoSQL.MQ.ES等解决比较高的并发访问,但是对于数据库来说,压力 还是太大,这时候即使数据库架构.表结构.索引等都设计的很好了,但 ...

  6. sublime中用less实现css预编译

    实现css预编译的方式有很多,听说glup很流行而且功能也很强大,但是就目前的工作而言,仅要css预编译和YUIcompress就够了,接下来切入正题 Less 是一门 CSS 预处理语言,它扩展了 ...

  7. laravel 下载报错:Unable to guess the mime type as no guessers are available

    在使用laravel的download()函数实现下载功能时,报错如下:Unable to guess the mime type as no guessers are available (Did ...

  8. Openlayers3 WebGis二次开发包实例

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="index.aspx.cs& ...

  9. netbeans性能分析文件保存位置

    C:\Users\Administrator\AppData\Roaming\NetBeans\8.2\config\HTTPMonitor 分析完,记得把文件删除,不然系统盘要满了

  10. netbeans 代码自动补全设置

    编辑器-----代码完成------语言选择"JAVA"------在如图红框中输入 @ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst ...