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
转载于:https://www.cnblogs.com/lonelyxmas/p/10817607.html
Directx教程(28) 简单的光照模型(7)相关推荐
- Directx教程(27) 简单的光照模型(6)
Directx教程(27) 简单的光照模型(6) 原文:Directx教程(27) 简单的光照模型(6) 从myTutorialD3D11_15到myTutorialD3D11_19的工程中,我们都只 ...
- Directx教程(24) 简单的光照模型(3)
在工程myTutorialD3D11_17中,我们重新定义我们的cube顶点法向,每个三角形面的顶点法向都是和这个三角形的面法向是一致的.如下图所示: 在该工程中,我们还修改了CubeModelCla ...
- 【Visual C++】游戏开发笔记四十一 浅墨DirectX教程之九 为三维世界添彩:纹理映射技术(一)...
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8523341 作者:毛星云(浅墨 ...
- 【Visual C++】游戏开发笔记四十三 浅墨DirectX教程十一 为三维世界添彩:纹理映射技术(二)...
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 作者:毛星云(浅墨) 邮箱: happylifemxy@163.com 本篇文章里,我们首先对Direct3D之中固定功能流水线中的 ...
- 【Visual C++】游戏开发五十六 浅墨DirectX教程二十三 打造游戏GUI界面(一)
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/16384009 作者:毛星 ...
- 【Visual C++】游戏开发五十七 浅墨DirectX教程二十四 打造游戏GUI界面(二)
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/16922703 作者:毛星 ...
- 【Visual C++】游戏开发四十八 浅墨DirectX教程十六 三维地形系统的实现
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...
- 【Visual C++】游戏开发笔记四十二 浅墨DirectX教程之十 游戏输入控制利器 DirectInput专场
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...
- 【Visual C++】游戏开发笔记四十七 浅墨DirectX教程十五 翱翔于三维世界 摄像机的实现
分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由zhm ...
- 【Visual C++】游戏开发笔记四十二 浅墨DirectX教程之十 游戏输入控制利器:DirectInput专场...
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/zhmxy555/article/details/8547531 作者:毛星云(浅墨) ...
最新文章
- python打开网页存图_python 获取网页图片 保存在本地
- Android踩坑日记:使用Fesco图片加载库在GridView上的卡顿优化
- vba 日期加一年_VBA究竟值不值得审计学?
- string中c_str()、data()、copy(p,n)函数的用法
- SpringBoot指南(五)——拦截器、原生组件
- phpmyadmin在nginx环境下配置错误
- (转)马云的江湖 PK 史玉柱的兵法
- 深度学习模型的可视化技术总结
- EasyRecovery的高级设置如何使用
- Jquery基础笔记
- 海康大华等传统摄像机的RTSP流通过拉转GB/T28181输出级联到国标流媒体服务平台
- dell笔记本驱动安装失败_戴尔笔记本win7系统声卡驱动无法安装的问题分析与解决方案...
- Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
- ECDSA 签名验证原理及C语言实现
- 使用man命令,出现 ”No manual entry for” 的解决办法
- 陈菜根谈“为什么子弹短信会火?”
- 阿里云服务器卸载宝塔面板
- android 系统设置向导,详解Android 手机卫士设置向导页面
- 微信小程序git提交代码
- iOS bitCode -- 360 加固保加固 iOS 应用所遇到的问题