Directx教程(28) 简单的光照模型(7)
原文: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

posted on 2019-05-06 08:31 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/10817607.html

Directx教程(28) 简单的光照模型(7)相关推荐

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

    Directx教程(27) 简单的光照模型(6) 原文:Directx教程(27) 简单的光照模型(6) 从myTutorialD3D11_15到myTutorialD3D11_19的工程中,我们都只 ...

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

    在工程myTutorialD3D11_17中,我们重新定义我们的cube顶点法向,每个三角形面的顶点法向都是和这个三角形的面法向是一致的.如下图所示: 在该工程中,我们还修改了CubeModelCla ...

  3. 【Visual C++】游戏开发笔记四十一 浅墨DirectX教程之九 为三维世界添彩:纹理映射技术(一)...

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

  4. 【Visual C++】游戏开发笔记四十三 浅墨DirectX教程十一 为三维世界添彩:纹理映射技术(二)...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 作者:毛星云(浅墨)    邮箱: happylifemxy@163.com 本篇文章里,我们首先对Direct3D之中固定功能流水线中的 ...

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

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

  6. 【Visual C++】游戏开发五十七 浅墨DirectX教程二十四 打造游戏GUI界面(二)

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

  7. 【Visual C++】游戏开发四十八 浅墨DirectX教程十六 三维地形系统的实现

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  8. 【Visual C++】游戏开发笔记四十二 浅墨DirectX教程之十 游戏输入控制利器 DirectInput专场

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  9. 【Visual C++】游戏开发笔记四十七 浅墨DirectX教程十五 翱翔于三维世界 摄像机的实现

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由zhm ...

  10. 【Visual C++】游戏开发笔记四十二 浅墨DirectX教程之十 游戏输入控制利器:DirectInput专场...

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

最新文章

  1. python打开网页存图_python 获取网页图片 保存在本地
  2. Android踩坑日记:使用Fesco图片加载库在GridView上的卡顿优化
  3. vba 日期加一年_VBA究竟值不值得审计学?
  4. string中c_str()、data()、copy(p,n)函数的用法
  5. SpringBoot指南(五)——拦截器、原生组件
  6. phpmyadmin在nginx环境下配置错误
  7. (转)马云的江湖 PK 史玉柱的兵法
  8. 深度学习模型的可视化技术总结
  9. EasyRecovery的高级设置如何使用
  10. Jquery基础笔记
  11. 海康大华等传统摄像机的RTSP流通过拉转GB/T28181输出级联到国标流媒体服务平台
  12. dell笔记本驱动安装失败_戴尔笔记本win7系统声卡驱动无法安装的问题分析与解决方案...
  13. Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
  14. ECDSA 签名验证原理及C语言实现
  15. 使用man命令,出现 ”No manual entry for” 的解决办法
  16. 陈菜根谈“为什么子弹短信会火?”
  17. 阿里云服务器卸载宝塔面板
  18. android 系统设置向导,详解Android 手机卫士设置向导页面
  19. 微信小程序git提交代码
  20. iOS bitCode -- 360 加固保加固 iOS 应用所遇到的问题

热门文章

  1. 求二叉树的深度(C++)
  2. Linux Apache服务详解——Apache虚拟目录与禁止显示目录列表实战
  3. WLAN概述——无线网络简介
  4. Linux之Firewall防火墙、iptables、firewalld
  5. 24. Swap Nodes in Pairs 1
  6. Oracle用户密码过期的处理方法
  7. VC++、MFC Sqlite3数据库的使用
  8. 解读2016之Golang篇:极速提升,逐步超越
  9. testlink配置修改
  10. android插件化-apkplug中OSGI服务基本原理-08