引言

在前面,我们已经讲述了,平行光源,点光源的使用方式,除了这两个之外,还有一个名为聚光灯的光源类型。聚光灯,当然是将光聚集在某个范围里面的光。想象一下,在一个万众瞩目的会场,大明星们登台出演。当他出现的那一刻,所有的聚光灯,都聚焦到它的身上!!!看看,聚光灯的威力是多么的大。在下面我们就来讲解如何模拟聚光灯。

聚光灯

其实,聚光灯的模拟很简单,它实际上就是一个带有范围的点光源而已。也就是说,我们会在上篇博客的基础上,对点光源的光照方程,增加上聚光灯的范围聚焦属性,来模拟出聚光灯来。所以,对聚光灯的模拟,就是如何对这个聚焦范围进行模拟而已。

为了,弄明白,如何对聚焦范围模拟,我们需要了解,聚光灯,是如何进行聚焦的。

首先,聚光灯和点光源一样,应该有一个位置pos,然后这里就与点光源不同,它应该有一个照射方向dir,不像点光源那样向四面八方照射光线。有了位置,和照射方向之后,我们就可以利用顶点的入射光向量,与这个聚光灯的照射方向进行点积运算,从而求出他们之间的夹角,如果夹角在我们规定的聚焦范围之内的话,就进行照射。

读者,可能觉得,这段话很熟悉。如果看过我前面几篇博客的话,就会知道,如何对这里的聚焦范围进行模拟了。没错,就是使用cos余弦,和指数运算来进行模拟。

下面是最后的照射方程公式:

读者可以发现,这个公式,只是多了前面的一部分,后面的部分完全和我前一篇博客中讲述的点光源的公式一样。也就是说,我们通过前面一部分的 公式来模拟聚光灯的聚焦能力。其中,L指的是顶点的光照向量,D是聚光灯照射的方向,S就是一个控制范围的指数变量,原因已经在讲述反射光的博客中讲述了,这里不再赘述。

实例解析

好了,理论的内容结束了。下面,我们使用聚光灯来做一个简单的Demo。

同样的,我们使用茶壶原型来做。我们在X-Z平面上绘制一片茶壶,这样,当聚光灯聚集在某个部分的时候,就能够看得很清楚。下面是绘制着一片茶壶的代码:

void CubeDemo::draw()
{//Set the vertex declarationHR(m_pDevice->SetVertexDeclaration(VertexPN::_vertexDecl));//Set the techniqueHR(m_pEffect->SetTechnique(m_hTechnique));//Set the gPowerstatic float power = 128.0f;HR(m_pEffect->SetValue(m_gPower,&power,sizeof(float)));//Set the gMaterialHR(m_pEffect->SetVector(m_gMaterial,&D3DXVECTOR4(0.0, 0.0, 1.0, 1.0)));//Set the gLightColorHR(m_pEffect->SetVector(m_gLightColor, &D3DXVECTOR4(0.8, 0.8, 0.8, 1.0)));//Set the gLightPosHR(m_pEffect->SetVector(m_gLightPos, &m_LightPos));//Set the gSpecularLightColorHR(m_pEffect->SetValue(m_gSpecularLightColor, &D3DXCOLOR(1.0,1.0,1.0,1.0),  sizeof(D3DXCOLOR)));//Set the gSpecularMaterialHR(m_pEffect->SetValue(m_gSpecularMaterial, &D3DXCOLOR(1.0,1.0,1.0,1.0), sizeof(D3DXCOLOR)));//Set the gAmbientLightColorHR(m_pEffect->SetValue(m_gAmbientLightColor, &D3DXCOLOR(0.1,0.0,0.1,0.0),sizeof(D3DXCOLOR)));//Set the gAmbientMaterialHR(m_pEffect->SetValue(m_gAmbientMaterial, &D3DXCOLOR(1.0,1.0,1.0,0.0), sizeof(D3DXCOLOR)));//Set the gA0HR(m_pEffect->SetFloat(m_gA0, 0.0f));//Set the gA1HR(m_pEffect->SetFloat(m_gA1, 0.0f));//Set the gA2HR(m_pEffect->SetFloat(m_gA2, 0.005));//Set the gLightDirHR(m_pEffect->SetValue(m_gLightDir, &D3DXVECTOR4(0, -1, 0, 0), sizeof(D3DXVECTOR4)));//Set the gSpotRangePowerHR(m_pEffect->SetFloat(m_gSpotRangePower, 10.0f));//Begin passUINT _pass = 0 ;HR(m_pEffect->Begin(&_pass, 0));HR(m_pEffect->BeginPass(0));//Draw the primitivedrawCube();//End passHR(m_pEffect->EndPass());HR(m_pEffect->End());
}
void CubeDemo::drawCube()
{for(int j = 0 ; j < 10 ; j ++){for(int i = 0 ; i < 10 ; i ++){//Create the world matrixD3DXMATRIX _worldM ;D3DXMatrixIdentity(&_worldM);D3DXMatrixTranslation(&_worldM,-20 + 4 * j,0,-20 + i * 4);//Set the gWVP matrixD3DXHANDLE _hWVP = m_pEffect->GetParameterByName(0, "gWVP");HR(m_pEffect->SetMatrix(_hWVP, &(_worldM* m_ViewMatrix* m_ProjMatrix)));//Set the gWorld matrixHR(m_pEffect->SetMatrix(m_gWorld, &_worldM));//Set the gInverseTransposeD3DXMatrixInverse(&_worldM,NULL, &_worldM);D3DXMatrixTranspose(&_worldM, &_worldM);HR(m_pEffect->SetMatrix(m_gInverseTranspose, &_worldM));HR(m_pEffect->CommitChanges());//Draw the teapotHR(m_TeaportMesh->DrawSubset(0));}// end for}// end for}

下面就是这个程序的Shader文件:

//---------------------------------------------------------------------------
// declaration  : Copyright (c), by XJ , 2014 . All right reserved .
// brief    : This file will define the SpotLight shader.
// date     : 2014 / 5 / 26
//----------------------------------------------------------------------------
uniform float4x4 gWVP ;             //这个变量将会保存世界变换矩阵*相机变换矩阵*透视投影矩阵的积//用这个矩阵,将点转化到裁剪空间中去uniform float4x4 gInverseTranspose;       //这个变量将会保存世界变换矩阵的逆矩阵*转置矩阵,用来对法向量进行变换uniform float4   gMaterial;         //这个变量用来保存顶点的材质属性,在本Demo中,将对所有的顶点使用相同的//材质uniform float4   gLightColor;           //这个变量将用来保存一个聚光灯光源的颜色uniform float3   gLightPos;            //这个变量用来保存聚光灯光源的位置uniform float4x4 gWorld;          //这个变量保存世界变换,用来对模型坐标进行变换,从而计算视向量uniform float4   gLightDir;           //这个变量呢将会保存聚光灯的照射方向uniform float    gSpotRangePower;        //这个变量将会保存聚光灯照射范围的大小uniform float3   gEye;              //这个变量保存视点的位置,也就是相机的位置uniform float    gPower    ;           //这个变量将会控制反射光的衰减速度uniform float4   gSpecularLightColor;     //反射光颜色uniform float4   gSpecularMaterial;      //物体对反射光的材质属性uniform float4   gAmbientLightColor;           //环境光颜色uniform float4   gAmbientMaterial;              //物体对环境光的材质属性uniform float    gA0;               //衰变参数a0uniform float    gA1;               //衰变参数a1uniform float    gA2;               //衰变参数a2//定义顶点着色的输入结构体
struct OutputVS
{float4 posH : POSITION0 ;float4 color : COLOR0 ;
};OutputVS SpotVS(float3 posL: POSITION0, float3 normalL: NORMAL0)
{//清空OutputVSOutputVS outputVS = (OutputVS) 0 ;//对顶点的法向向量进行变换normalL = normalize(normalL);float3 normalW = mul(float4(normalL, 0.0f),gInverseTranspose).xyz;normalW = normalize(normalW);//由于是聚光灯光源,每一个顶点的光照向量都不相同,需要重新计算:float3 posW = mul(float4(posL, 1.0), gWorld).xyz ;float3 lightVec = gLightPos.xyz - posW ;lightVec = normalize(lightVec);//根据漫反射公式:// Color = max(L * Normal, 0)*(LightColor*Material)float s = max(dot(lightVec,normalW), 0);float3 diffuse = s*(gMaterial*gLightColor).rgb ;//根据环境光公式:// Color = AmbientColor * AmbientMaterialfloat3 ambient = (gAmbientLightColor * gAmbientMaterial).rgb ;//根据反射光公式:// Color = pow((max(dot(r,v),0)),p) * (SpecularLightColor*SpecularMaterial)float3 view = gEye - posW ;view = normalize(view);float3 ref = reflect(-lightVec, normalW);float t = pow(max(dot(ref,view),0),gPower);float3 specular = t * (gSpecularLightColor * gSpecularMaterial).rgb ;//计算聚光灯的衰变值,根据如下公式:// attenuation = pow((max(dot(dir, lightVec),0)), SpotPower)float spot_attenuation = pow(max(dot(gLightDir, -lightVec),0), gSpotRangePower);//计算漫反射和反射光的衰变值公式如下:// attenuation = a0 + a1*d + a2*d*dfloat dist = distance(gLightPos, posW);float attenuation = gA0 + gA1*dist + gA2 * dist * dist ;//计算最后的颜色outputVS.color.rgb = spot_attenuation * ((diffuse  + specular)/attenuation + ambient);outputVS.color.a = gMaterial.a ;//使用gWVP将世界坐标转化为裁剪坐标outputVS.posH = mul(float4(posL, 1.0f), gWVP);//返回结果return outputVS ;
}// end for Vertex Shaderfloat4 SpotPS(float4 c: COLOR0): COLOR
{return c ;
}// end for Pixel Shadertechnique SpotTech
{pass P0{vertexShader = compile vs_2_0 SpotVS();pixelShader =  compile ps_2_0 SpotPS();}
}

最后是程序的截图,运行这个程序,可以按I,或者K键来控制聚光灯的高度,按A或者D来控制聚光灯在X轴上的位置,使用鼠标控制场景的放大和缩小:

好了,今天又结束了。程序实例已经上传,可自行下载。

DirectX 9.0 (6)聚光灯相关推荐

  1. DirectX 9.0 SDK安装

    VC6.0+DirectX 9.0 SDK Update (Summer 2004) 下载后安装到根目录. 编译: Samples\C++\DirectShow\BaseClasses的项目,得到开发 ...

  2. DirectX 8.0 简介 (转)

    DirectX 8.0 简介 (转)[@more@] DirectX112000>作者:Philip Taylor DirectX 8.0 简介 欢迎关注 Driving DirectX.在本月 ...

  3. DirectX 9.0 (4)环境光和反射光

    引言 在上一节的DirectX 9.0 系列中,我们讲述了光和材质的交互,以及最基本的平行光漫射光模型.但是,为了使我们模拟的物体,更加的真实,我们应该还要加上其他的光彩效果才可以,这样就会使的光效果 ...

  4. 一种基于DirectX 9.0 API的G代码逆向渲染方法

    G代码是一种工业加工描述语言,现在也广泛的运用于3D打印中.但G代码是一种单向的描述语言,很难逆向回三维模型.但近日,日本出现了一款名为MakePaintable的软件,它可以将G代码逆向回三维模型. ...

  5. DirectX 9.0 (3) 漫射光

    引言 在计算机图形中,为了使的图形看上去具有立体的效果,我们需要为我们的3D物体,加上一点光照效果.如果你学过绘画的课程,就会知道,一个物体,如何想要画的具有立体的感觉,我们需要对物体进行光照处理.比 ...

  6. DirectX 9.0 3D 笔记

    1.3.0 预备 1.HAL,硬件抽象层,由D3DDEVTYPE_HAL指定 2.REF,参考光栅设备 3.COM,组件对象模型,使之向下兼容,视为C++类. 1.3.1 表面 4.IDirect3D ...

  7. 《DirectX 9.0 3D游戏开发编程基础》 第二章 绘制流水线 读书笔记

    模型的表示 场景:物品或模型的集合 任何物品都可以用三角形网络逼近表示.我们经常用以下术语描述三角形网络:多边形(polygons).图元(primitives).网络几何单元(mesh geomet ...

  8. DirectX 9.0 C Jun 2010 Redist, 游戏必备

    Microsoft微软DirectX 9.0c最新官方正式多语言版For Win9x/ME/2000/XP/2003.与先前发布DirectX 9.0b相比较而言,新版DirectX 9.0c加入了对 ...

  9. DirectX 9.0 C 多国语言正式版(官方下载)

    微软终于放出了DirectX 9.0c官方正式版,此最新版的版本号与先前报道的在微软XP SP2 2126测试版补丁中所集成的版本一样,同为4.09.0000.0904,但此版本为最终零售版.有消息说 ...

最新文章

  1. Python使用matplotlib可视化两个时间序列的交叉相关性图、交叉相关图显示了两个时间序列之间的滞后性(Cross Correlation plot)
  2. 【Java线程】深入理解Volatile关键字和使用
  3. Spring Boot基础学习笔记23:用户自定义授权管理
  4. 2020-09-09
  5. 要素集获取要素_OGC的网络要素服务(WFS)(持续更新。。。)
  6. python 替换array中的值_Python实现计数排序
  7. 新手如何使用Docker来搭建PHP开发环境?
  8. Java 线程第三版 第八章 Thread与Collection Class 读书笔记
  9. (超详细)算法学习:STL和基本数据结构
  10. 2018-2-13-win10-UWP-RSS阅读器
  11. python自动排版公众号_如何实现公众号排版自动化?微信公众号一键排版软件推荐...
  12. 腾讯云学生服务器搭建个人网站——配置web开发环境详细步骤
  13. 单片机中断程序,如何被中断?
  14. cadence SPB17.4 - orcad - exprot sch PDF
  15. 冷热水龙头_冷热水龙头原理是什么 冷热水龙头原理及结构图
  16. Python让Excel飞起来—批量处理工作薄和工作表
  17. 挂载文件系统和查找文件
  18. MKS TinyBee V1.0使用说明书
  19. 在云中实现可信的Luna SA解决方案
  20. 爬虫入门——爬虫可以采集哪些格式的数据?

热门文章

  1. 同款蓝牙耳机为什么会串联_蓝牙耳机凭什么成网红明星标配时尚单品?揭秘三大原因...
  2. 3C及CQC等认证流程介绍
  3. java计算机毕业设计高速公路收费管理MyBatis+系统+LW文档+源码+调试部署
  4. (无插件) vim 基础快捷键汇总
  5. 高速公路智能报警预警系统的应用
  6. 博易大师指标公式源码大全学习
  7. PDF设置从上次阅读的位置继续阅读
  8. 基于STM32的PS2游戏手柄智能小车
  9. LwIP协议栈之ICMP(Internet Message Protocal)协议
  10. IDEA界面的主题风格-黑白界面修改