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)的更多相关文章
- Directx教程(29) 简单的光照模型(8)
		
原文:Directx教程(29) 简单的光照模型(8) 现在我们新建一个工程myTutorialD3D_23,在这个工程中,对前面一章的代码进行一些整理: 1.我们在顶点属性中增加材质的的漫 ...
 - Directx教程(27) 简单的光照模型(6)
		
原文:Directx教程(27) 简单的光照模型(6) 从myTutorialD3D11_15到myTutorialD3D11_19的工程中,我们都只有一个光源,光源的位置在LightCla ...
 - Directx教程(26) 简单的光照模型(5)
		
原文:Directx教程(26) 简单的光照模型(5) 在前面的工程中,我们都是在vs中实现顶点光照计算,然后再把顶点颜色传到ps中.本章中我们尝试fragment光照(或者说叫ps光照),在 ...
 - Directx教程(25) 简单的光照模型(4)
		
原文:Directx教程(25) 简单的光照模型(4) 在本篇日志中,我们尝试用不带衰减的点光源来计算漫反射颜色. 前面的三个工程,我们都用的是方向光源(directional li ...
 - Directx教程(24) 简单的光照模型(3)
		
原文:Directx教程(24) 简单的光照模型(3) 在工程myTutorialD3D11_17中,我们重新定义我们的cube顶点法向,每个三角形面的顶点法向都是和这个三角形的面法向是一致 ...
 - Directx教程(23) 简单的光照模型(2)
		
原文:Directx教程(23) 简单的光照模型(2) 在工程myTutorialD3D11_16中,我在文件light.vs中定义了一个材质光源属性常量缓冲. //const buffer最好 ...
 - Directx教程(22) 简单的光照模型(1)
		
原文:Directx教程(22) 简单的光照模型(1) 在前面的教程中,我们在顶点属性中直接给顶点赋颜色,这样生成的三维物体缺乏真实感,如下图中两个立方体,左边的是通过光照生成物体表面颜色的 ...
 - 【Visual C++】游戏开发五十六 浅墨DirectX教程二十三 打造游戏GUI界面(一)
		
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/16384009 作者:毛星云 ...
 - [译]Vulkan教程(28)Image视图和采样器
		
[译]Vulkan教程(28)Image视图和采样器 Image view and sampler - Image视图和采样器 In this chapter we're going to creat ...
 
随机推荐
- 洛谷P3747 [六省联考2017]相逢是问候
			
传送门 题解 扩展欧拉定理. 线段树维护,已经全改到底了的节点就不管,不然暴力修改下去. //Achen #include<algorithm> #include<iostream& ...
 - VS 快捷键和正则替换
			
本文在VS2017中可用 1.注释 :Ctrl K C 取消注释: Ctrl K U 2.整理代码格式: Ctrl K D 或者 Ctrl K F 3.快速切换不同的代码窗口 Ctrl+Tab 4 ...
 - RxJS/Cycle.js 与 React/Vue 相比更适用于什么样的应用场景?
			
RxJS/Cycle.js 与 React/Vue 相比更适用于什么样的应用场景? RxJS/Cycle.js 与 React/Vue 相比更适用于什么样的应用场景? - 知乎 https://www ...
 - java基础之自定义单链表练习
			
一.单链表 1.单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置), ...
 - SQLSTATE[HY000] [2002] 乱码
			
string(59) "SQLSTATE[HY000] [2002] ����Ŀ����������ܾ��������ӡ� " 实际意思是:SQLSTATE[HY000] [20 ...
 - Leetcode415Add Strings字符串相加
			
给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和. 注意: num1 和num2 的长度都小于 5100. num1 和num2 都只包含数字 0-9. num1 和num2 都不包 ...
 - SPOJ 2916 GSS5 - Can you answer these queries V
			
传送门 解题思路 和GSS1相似,但需要巨恶心的分类讨论,对于x1<=y1< x2< =y2 这种情况 , 最大值应该取[x1,y1]的右端最大+[y1+1,x2-1]的和+[x2, ...
 - myql 配置项
			
提高数据插入速度方法 bulk_insert_buffer_size 默认:8M (8*1024*1024) 参考网址:https://stackoverflow.com/questions/2030 ...
 - JS文字翻滚效果
			
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtm ...
 - Python基础-列表、元组、字典、字符串
			
Python基础-列表.元组.字典.字符串 多维数组 nums1 = [1,2,3] #一维数组 nums2 = [1,2,3,[4,56]] #二维数组 nums3 = [1,2,3,4,['a ...