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

首先,我们学习一下最简单的phong光照模型:
在phong光照模型中,物体表面的颜色由自发射光(emissive)、环境光(ambient)、漫反射光(diffuse)以及镜面高光(specular)四部分组成,每一部分又是通过物体表面的材质属性和光照属性一起来决定。用公式来表示就是:
surfaceColor = emissive + ambient + diffuse + specular
自发射光(emissive):

它表示物体本身具有发射光的属性,它是独立于光源的,同时她它本身也不是光源,不会对场景中的其它为物体有影响。通常emissive用一个常量颜色来表示。
emissive = Ke, Ke表示材质的自发射光属性。
环境光(ambient):

环境光模拟场景中来自于来自于各个方向的光线,这些光线也没有位置的概念,比如白天我们在房间里,没有任何特定光源,但我们房间确实亮的。通常它等于
ambient = Ka x globalAmbient
Ka表示材质的环境光反射系数,globalAmbient表示入射光线的环境光系数,它们通常都是2个颜色常量。
漫反射光(diffuse):

漫反射光通常指方向光在物体表面不同方向的反射光,如上图所示,在粗糙的表面上,入射光的反射投向不同的方向。反射光的计算通常用Lambert定律:
diffuse = Kd x lightColor x max(N · L, 0)
- Kd 是材质的漫反射颜色系数, lightColor 是入射光的颜色 、
- N 是物体表面的法向
- L 是顶点朝向光源的归一化向量
- P 是着色的顶点位置
高光(specular):
在光滑的表面,比如金属球,通常有高光的效果。高光通常是物体光滑表面的镜面反射散射效果。

高光和光源方向和视点都有关系,它的计算公式如下:
specular = Ks x lightColor x facing x (max(N · H, 0)) shininess
- Ks 是材质的高光系数, lightColor是光源颜色,shininess是高光系数,通常是一个常量。
- N 是归一化的物体表面法向
- V 朝向视点的归一化向量
- L 是顶点朝向光源的归一化向量
- H 等于归一化的向量(V+L)/2
- P 是着色的顶点位置
- 如果N · L > 0,facing 是 1 ,否则是0

了解了基本的光照模型以后,我们开始光照程序的编写:
首先,新建一个CubeModelClass类,该类表示一个cube立方体,但和ModelClass类不同的是,在顶点结构中我们去掉了color属性,增加了normal属性。
struct VertexType
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal; //法向
};
该立方体中心在原点,每个顶点的法向,我都取原点到该顶点位置的归一化向量(在shader中实现归一化,给顶点法向赋值时,我并没有做归一化操作)。每个顶点法向位置大概如下图红色线段所示:

接下来,我们要定义两个新的shader文件light.vs和light.ps,新的基于材质和光源的物体渲染,将使用这两个文件。这两个文件的中光照计算公式就是利用上面的讲的phong光照原理。
surfaceColor = emissive + ambient + diffuse + specular
我们在light.vs中实现光照计算,需要注意的是,在利用漫反射(高光)时候,我用了方向光(directional light,所有光线都是一个方向,比如无穷远处的光源,类似太阳光),代码大致如下:
//自发射颜色
float3 emissive = float3(0.0, 0.0, 0.0);
//计算环境光
float3 ambient = float3(0.3, 0.3, 0.3);
//计算漫反射光
float3 L = normalize(float3(-1.0, -1.0, 1.0));
float diffuseLight = max(dot(N, L), 0);
float3 diffuse = diffuseLight;
//计算高光
float3 V = normalize(cameraPosition - P);
float3 H = normalize(L + V);
float specularLight = pow(max(dot(N, H), 0), 5.0);
if (diffuseLight <= 0)
specularLight = 0;
float3 specular = specularLight;
output.color.xyz = emissive + ambient + diffuse + specular;
接下来,我们又定义LightShaderClass类,主要用该类实现light.vs和light.ps的载入,参数初始化以及执行shader等功能。
最后就是在GraphicsClass中创建LightShaderClass和CubeModelClass类,渲染这个新的cube对象(老的modelClass也是一个cube,但我们用colorShader渲染它,并且它的位置也被挪到右边)。
程序运行后的界面如下:

完整的代码请参考:
工程文件myTutorialD3D11_15
代码下载:
http://files.cnblogs.com/mikewolf2002/myTutorialD3D11.zip
Directx教程(22) 简单的光照模型(1)的更多相关文章
- Directx教程(29) 简单的光照模型(8)
原文:Directx教程(29) 简单的光照模型(8) 现在我们新建一个工程myTutorialD3D_23,在这个工程中,对前面一章的代码进行一些整理: 1.我们在顶点属性中增加材质的的漫 ...
- Directx教程(28) 简单的光照模型(7)
原文:Directx教程(28) 简单的光照模型(7) 现实生活中的点光源都是随着距离衰减的,比如一个电灯泡在近处会照的很亮,远处光线就很弱.本节中我们在前面光公式的基础上,再给漫反射和 ...
- 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最好 ...
- 【Visual C++】游戏开发五十六 浅墨DirectX教程二十三 打造游戏GUI界面(一)
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/16384009 作者:毛星云 ...
- Playmaker全面实践教程之简单的使用Playmaker示例
Playmaker全面实践教程之简单的使用Playmaker示例 简单的使用Playmaker示例 通过本章前面部分的学习,相信读者已经对Playmaker有了一个整体的认识和印象了.在本章的最后,我 ...
随机推荐
- LUOGU P1965 转圈游戏 (Noip 2013)
传送门 解题思路 比较简单的模拟题,转圈一定有一个循环节,而且循环节长度一定小于m,因为循环节是一个%m的剩余系,然后一遍模拟记录下来循环节,快速幂即可. #include<iostream&g ...
- HDU4004 二分答案
第一道二分答案...今天看了大牛的博客,突然发现有个叫“二分枚举答案”的方法好像很牛,于是便搜了些资料..发现并不是很难,可能是我了解的只是冰山一脚罢了...加油ACMer!!!! #include& ...
- sde中的shp数据无法编辑
最近整理空间数据库时,用sde比较多,发现在编辑sde中的数据时总是出现数据被锁或者是被其他应用程序占用.用了很多方法处理,但不是每个方法都实用.下面讲的是我在删除shp或者给shp增加字段时所遇到的 ...
- jeecms v9.3 has a stroed xss vulnerability
转载:https://blog.csdn.net/libieme/article/details/83588929 jeecms v9.3 has a stroed xss vulnerability ...
- phpStrom编辑器 通过 git 提交代码到 gitlab
前提: 1.已经成功安装 git: 2.将 phpstrom 和 gitlab 连接起来.参考此文章 一.在 phpstrom 中打开需要推送的项目 二.将 ‘工作区’ 代码 添加到 ‘暂存区’ 三. ...
- 《DSP using MATLAB》Problem 7.33
代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...
- Python模块安装方式
一.方法1: 单文件模块直接把文件拷贝到 $python_dir/lib/python3.4/site-packages/ 二.方法2: 多文件模块,带setup.py 下载模块包,进行解压,进入模块 ...
- selenium自动化方式爬取豆瓣热门电影
爬取的代码如下: from selenium import webdriver from bs4 import BeautifulSoup import time #发送请求,获取响应 def get ...
- Spring的IoC容器(转)BeanFactory
Spring的IoC容器 Spring读书笔记-----Spring的Bean之Bean的基本概念 加菲猫 Just have a little faith. Spring的IoC容器 (用户持久化类 ...
- VUE打包好的文件部署让beego实现静态文件访问,如何用根目录来访问静态文件?
最近的一个全栈项目,光伏云监控系统,后端使用beego框架,纯api,前端使用VUE2.0.项目地址:http://scada.ssechina.com:88/static 我把打包好的前端文件放到g ...