首先我们将要了解如下问题
1. 学习Direct3D支持的光照资源, 以及它们照射出的灯光类型
2. 弄懂怎样定义灯光去影响其照射的表面
3. 找出怎样算出描述三角形的方向以便我们能够确定光线照射到三角形的角度
我们在这里将融合《3D游戏编程大师技巧》和《Direct3D》的部分内容。
即, 将它们一一映射。
颜色模型和材质
物体的材质决定了它将如何于光线交互, 材质用来描述物体被光线照射后将对光线产生何种影响。学习过物理课, 我们知道不同材料,或者说不同的原子对光子产生不同的影响。
这里说,也许不是那么容易理解, 我们还是来看看究竟光是什么吧。
首先我们回顾下光的基本的特性:
一、 光可以沿着直线传播
二、 光会发生折射
三、 光会发生反射
四、 光会发生色散
五、 光会发生干涉
六、 光会发生衍射
七、 光是一种电磁波
八、 光存储偏振
九、 光的高聚合形态-激光
十、 光电效应和光子
十一、 光即是波又是粒子
看, 我们的高中物理部分所讲解的光的现象有这么多有关光的特性。
下面我们将简述光的特性, 并联系如何联系到用Direct3D表达出来。
能够发光的物体叫做光源(Light Source). 太阳就是一个巨大的自然光源。
而到了夜晚人们不得不自己制作人造光源。人造光源有火把。蜡烛,电灯
等等。 根据光源发射光的不同性质, 我们可以将光源简单的归类:
一、 定向光源
定向光源是没有确切位置的光源, 它离场景非常远, 其光线平行第照射到表面(surface)上, 这种光源也被称为无穷远光源。定向光源的特征是其光照强度(Light Intensity)不会随距离而衰减, 这是因为光线已经传播了无穷远的距离。 定向光源本身也有强度和颜色。要定义定向光源, 只需指定其初始颜色和强度即可。为了表示光源的光照强度我们有这么个公式:
I(d)dir = I0dir * Cldir ( 光照强度 = 初始光源强度 * 光源颜色 )
I0dir - 表示初始光源强度, Cldir 表示光源的颜色, I(d)dir 表示将产生目标光的光照强度。 那么Direct3D中如何表示呢?
首先我们来看一个结构, 我们以Direct3D9为主:
typedef struct _D3DLIGHT9 {
D3DLIGHTTYPE Type; //光源的类型
D3DCOLORvalue Diffuse; //光源发出的漫射光颜色
D3DCOLORvalue Specular; //光源发出的镜面反射光颜色
D3DCOLORvalue Ambient; //光源发出的环境光颜色
D3DVECTOR Position; //光源的位置, 只对点光源和聚光灯有效
D3DVECTOR Direction; //光源的方向
float Range; //光照射的范围
float Falloff; //对聚光灯有效,表示内锥到外锥之间的光照强度衰减,通常为1.0f
float Attenuation0; //对点光源和聚光灯有效
float Attenuation1; //对点光源和聚光灯有效
float Attenuation2; //对点光源和聚光灯有效
float Theta; //只用于聚光灯,指定内锥的角度,单位是弧度
float Phi; //只用于聚光灯,指定外圆锥的角度,单位是弧度
} D3DLIGHT9;
这个结构用来存储光的属性
那么, 我们就利用这个结构来定制出不同的光源类型,其中D3DLIGHTTYPE Type; 有三种不同取值分别和点光源,定向光源,聚光灯一一对应,分别为:D3DLIGHT_POINT, D3DLIGHT_DIRECTIONAL, D3DLIGHT_SPOT.
定向光源最直接的现实例子就是我们的太阳, 它离地球非常远, 它的光线平行的照射到地球表面上,它的光不衰减。
二、 点光源
点光源用来表示实际生活中的电灯等形状像点一样的光源, 其光照强度随光源离表面S的距离衰减, 衰减使用三个因子来模拟, 常量衰减因子(kc)、线性衰减因子(kl)和二次衰减因子(kq) 用d (distance)表示位于点p处的点光源和表面S上的点s之间的距离, 光照强度和距离的关系如下
I(d)point = I0point * Clpoint / kc + kl * d + kq * d^2
其中 d = |p-s|
Andre LaMothe在实际应用中,发现不包含二次项的更简单的光源模型也很好使:
I(d)point = I0point * Clpoint / kc + kl * d;
三、 聚光灯
聚光灯的现实例子可以认为是手电筒,我们家唯一的家用电器。或者类似于手电筒的发光设备, 比如探照灯, 它们的特征是, 当光源将光线投射到表面时,会形成内锥和外锥。其中内锥的光照强度高一些,并逐步向外锥衰减。由于聚光灯复杂很多,所以在实时游戏中, 非常粗略地模拟聚光灯的模型就能满足需要。 我们使用简化后的公式:
I(d)spotlight = I0spotlight*Clspotlight * MAX(cosθ,0)^pf / kc + kl*d + kq*d^2
其中 d = |p-s| pf 为指数因子。
了解了三种基本光源类型后, 我们来看看前面没有展开的话题:
一、 光可以沿着直线传播
光在空气中沿着直线传播, 在水、玻璃等透明物质中的传播路线也是直的。
所以我们把光的传播方向的直线叫做光线(ray)。但是光线必须在均匀的介质中才沿着直线传播, 如果介质不均匀光线也会发生弯曲。例如地球周围的大气就是不均匀的。所以我们可以说 光在均匀介质中是沿着直线传播的。如果了解了引力的作用,我们也可以说在一般引力环境下,光线将沿着直线传播,如果在强引力作用下光线也将发生弯曲。
二、 光会发生折射(refraction)
光从一种介质斜射入另一种介质(medium)时, 传播方向一般会发生变换, 这种现象叫做光的折射。前面说过光从不均匀的空气中传播路径是弯曲的, 实际上这也是折射现象。
折射光线和入射光线分居法线两侧, 当入射角不和介质表面垂直时传播方向将改变。当垂直时,传播方向不变。
三、 光会发生反射
从光的入射点O 所做的垂直于镜面的线ON叫做法线, 入射光线与法线的夹角叫做入射角, 反射光线与法线的夹角叫做反射角。
光的反射可以分为镜面反射(Specular reflect)和漫反射(Diffuse reflect)
镜面很光滑, 射到平面镜上的平行光线反射后仍然是平行的。光滑镜面的反射叫做镜面反射。
一个凹凸不平的物体的表面被光线照射会发生漫反射(Diffuse reflect)。
不同介质的折射率不同, 我们把折射率较小的介质称为光疏介质(medium) , 折射率较大的介质称为光密介质。光疏介质和光密介质是相对的, 比如拿水、水晶和金刚石三种物质比较, 水晶对水来说是光密介质。对金刚石来说是光疏介质。当入射角达到一定程度,使折射角达到90度时,折射光完全消失, 只剩下反射光, 这种现象叫做全反射。
可见,很多时候光线的折射现象和反射现象是交互(interactive)发生的, 随时将因为入射角的改变而导致仅反射, 即反射又折射。
四、 光会发生色散
棱镜也叫三棱镜。 楞镜可以改变光的传播方向还可以使光发生色散。太阳、日光灯等发出的光, 没有特定的颜色, 叫做白光。一条光线照射到棱镜上,我们预期会看到白色亮线,但是实际上却出现了许多不同颜色的亮线。这条亮带叫做光谱。 这个现象说明白光实际上是由各种单色光组成的复色光。复色 在介质中由于折射率不同分解成单色光的现象, 叫做光的色散。
五、 光会发生干涉
我们现在已经知道,光即是李子又是电磁波,可以这样理解,光粒子沿着波动轨迹运动。那么我们先看由于光发生干涉而说明光是一种波的现象。首先我们看波的干涉。频率相同的两列波叠加, 使某些区域的振动加强, 某些区域的振动减弱, 而且振动加强的区域和振动减弱的区域相互隔开。 这种现象叫做波的干涉。 1801年,英国物理学家托马斯 杨在实验室里成功第观察到了光的干涉。 光发生干涉现象时, 光在一些地方互相加强, 在另一些地方互相削弱。
六、 光会发生衍射
光的衍射, 波的衍射现象, 波可以绕过障碍物继续传播, 这种现象叫做波的衍射。
由于光的波长很短, 所以一般我们看不到光的衍射现象。 而当光射向一个针孔、一条狭缝、一根细丝时, 可以清楚地看到光的衍射现象。
七、 光是一种电磁波
光的衍射和干涉证明了光是一种波。19世界60年代,麦克斯韦预先了电磁波的存在,并从理论上得出, 电磁波在真空中的传播速度应为3.11x10^8m/s, 而当时实验测得的光速为3.15x10^8m/s, 所以他认为这不是一种巧合, 它表明光与电磁现象之间有本质的联系。由此它提出光的本质上是一种电磁波。后来经过赫兹的实验证明光的速度和电磁波的速度确实相同, 这样就证明了光的电磁说的正确性。
八、 光的偏振
光的干涉和衍射现象说明光具有波动性, 但不能确定光究竟是横波还是纵波。但是光的偏振现象说明, 光是横波。 太阳、电灯等普通光源发出的光, 包含这垂直于传播方向上沿一切方向振动的光, 而且沿着各个方向振动的光波的强度都相同。 这种光叫做自然光。 自然光通过偏振片P(叫做起偏器)之后, 只有振动方向跟偏振片的透振方向一致的光波(light-wave)才能通过。 也就是说, 通过偏振片P的光波, 在垂直于传播方向的平面上, 只沿着一个特定的方向振动。 这种光叫做偏振光。 横波只沿着某一个特定的方向振动, 称为波的偏振。
九、 光的高聚合形态-激光
这种光非常好,我们经常期望在游戏中实现激光效果。Laser
普通光源由于向各个方向发射的光是不确定的, 发光频率也不一样, 所以这样的光叫非相干光。 只有频率相同、并满足一定条件的光才是相干光。 激光是一种人工产生的相干光。
激光的平行度非常好, 可以传播很远的距离后仍能保持一定的强度。
激光的亮度高, 在很小的空间和很短的时间内集中很大的能量。即, 激光可以产生高温高压条件。
十、 光电效应和光子
光电效应 – 在光照射下物体发射电子的现象, 叫做光电效应, 发射出来的电子叫做光电子。 最开始发现光电效应时物理学家们没有感到惊奇, 认为当光入射金属时, 金属里的自由电子会由于变化着的电场的作用而振动。 如果光足够强, 振幅足够大, 不论光的频率高低, 经过一段时间后电子的振幅就会很大, 就有可能飞出金属表面。
但是进一步研究发现, 对各种金属都存在着极限频率和极限波长, 如果入射光的频率比极限频率低, 那么无论光多强, 照射时间多长, 都不会发生光电效应。如果入射光频率高于极限频率, 即使光不强, 当它射到金属表面时也会观察到光电子的发射。
光电效应具有瞬时性, 即无论光的亮度如何,只要高于极限频率 光电子的产生都几乎是瞬时的, 不超过10^-9s
1900年, 德国物理学家普朗克在研究物体热辐射(radiation)的规律时发现, 只有认为电磁波的发射和吸收不是连续的, 而是一份一份地进行的, 理论计算的结果才能跟实验事实相符。这样的一份能量叫做能量子。 普朗克还认为每一份的能量子等于hv, 其中v是辐射电磁波的频率, h是一个常量, 叫做普朗克常量。 h = 6.63x10^-34Js.
受普朗克启发, 爱因斯坦于1905年提出, 在空间传播的光也不是连续的, 而是一份一份的, 每一份叫做一个光量子, 简称光子。 E = hv
那么 由于光本身是一种电磁波, 所以根据普朗克的结论, 光量子就是能量子。
好以上即浓缩了一份关于初中和高中关于光的特征的常识。
光照计算是基于大量的面法线(face normal)的, 这要求我们必须根据预先计算好的法线来执行光照计算: 要么在背面消除阶段执行光照计算, 要么在背面消除阶段将法线存储起来,以便在光照计算阶段使用它们。
着色处理
着色处理发生在光栅化和指定图元上的顶点颜色怎样被计算成像素颜色之间。目前这里有三种着色模式可用: 平面着色(float shading)和高洛德(Gouraud shading)。平面着色,图元像素的颜色是均匀的, 且就是指定图元第一个顶点的颜色。 因此一但三角形的第一个顶点被指定成红色, 那么它的其他三个顶点也将会是红色。
高洛德着色, 图元表面的颜色是由每个顶点通过线性插值来赋予。
着色模式受Direct3D设置状态决定。
IDirect3DDevice9::SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
IDirect3DDevice9::SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
IDirect3DDevice9::SetRenderState(D3DRS_SHADEMODE, D3DSHADE_PHONG);
光照首先要处理的如何定义光源, 如何执行着色, 如何定义材质。而纹理,材质(介质), 光照都可以看做是增强真实感的部分。
面法线(face normal) 是描述多边形表面方向的一个向量。
顶点法线(Vertex normals)也是基于同样的概念, 但是我们与其指定每个多边形的法线, 还不如为每个顶点指定。
分享到:
相关推荐
这个资源提供的示例程序是一个D3D11光照计算模型,旨在帮助开发者理解和实现光照效果在3D场景中的应用。 光照计算在3D图形学中至关重要,它决定了物体表面的视觉表现,如颜色、亮度和阴影。D3D11通过硬件加速来高效...
本项目“shader_solid7kb_纹理贴图opengl_shader光照计算_SHADER_源码”关注的是使用OpenGL Shaders进行纹理贴图和光照计算,以实现一个旋转的四面体模型。 1. **OpenGL着色器**:OpenGL提供两种类型的着色器,顶点...
非结构化网格的数据体光照计算是渲染这些复杂模型时的关键步骤,它涉及到对网格中的每个像素或样本点进行光照效果的精确计算。本文将探讨基于GPU(图形处理器)的非结构化网格数据体光照计算及其实现方法。 GPU,...
现代OpenGL+Qt:使用halfway向量提高光照计算效率,使用halfway向量提高OpenGL光照计算的效率,详见博文:现代OpenGL+Qt学习笔记之十一:使用halfway向量提高光照计算效率...
4. **光照计算**:评估交点处的光照条件,包括直射光、环境光和间接光照(即光的反射和折射)。间接光照是实现全局光照的关键,它能产生阴影和反射的层次感。 5. **次级光线**:对于有反射或折射的表面,需要发射新...
OpenGL作为一个强大的跨语言、跨平台的编程接口,为开发者提供了丰富的功能来实现复杂的光照计算。 在OpenGL中,光照模型主要由光源、物体表面属性和环境因素三部分构成。光源可以有多种类型,如点光源、方向光和...
同时,不要忘记考虑优化光照计算,以确保在复杂场景中的性能表现。 总之,OpenSceneGraph提供了强大的光照系统,允许开发者精细地控制3D场景中的照明效果。通过理解全局光和混合光的概念,以及如何在osg中实现和...
HLSL是一种专门用于DirectX图形API的着色语言,它允许程序员在GPU上编写计算密集型代码,如光照计算,从而提高渲染性能。与传统的固定功能管线相比,使用HLSL的可编程管线提供了更大的灵活性和控制力。 1. **每顶点...
当所有几何信息存储完毕后,再根据G-Buffer的内容进行光照计算,一次性处理所有光源对每个像素的影响。 优点: - 高效处理大量光源:延迟渲染可以轻松应对成百上千的动态光源,因为光照计算是在像素级别上进行的。 ...
而延迟光照则是先将场景的所有几何信息存储到称为“几何缓冲区”(G-Buffer)的纹理中,然后在后处理阶段对这些信息进行光照计算。这样,每个像素只需要处理一次,无论场景中有多少光源,都只在这个像素的位置进行...
不用担心性能问题,平台通用,缺点是难以使效果与环境产生交互。 仅供交流学习,请勿商业用途!
1. **光照计算基础**:卫星的光照条件取决于其轨道参数(如轨道高度、倾角、升交点赤经等)以及地球与太阳的相对位置。这需要了解天体力学的基本概念,包括开普勒定律和天球坐标系统。 2. **`sun.m`**: 这可能是...
本文将深入探讨片段着色器和顶点着色器在光照计算中的应用,并对比它们各自的优缺点。 首先,我们来了解两个基本的着色概念:顶点着色和片段着色。顶点着色器是在GPU上运行的程序,主要处理顶点数据,如位置、法线...
在GL_illuminationBase这个压缩包中,可能包含了一系列的源代码文件,如顶点着色器和片段着色器,它们负责在GPU上执行光照计算。这些着色器程序会根据输入的顶点坐标、法线向量和光照信息来生成最终的颜色输出。此外...
在Unity引擎中,光照贴图烘焙(Lightmap Baking)是一种优化光照计算的方法,它可以将复杂的光照信息预先计算并存储到贴图中,以便在运行时以较低的性能成本渲染场景。然而,当游戏场景中存在大量预制体(Prefab)且...
在OpenGL中,我们可以使用glLight和glMaterial函数来设置光源和物体材质,然后通过glEnable(GL_LIGHTING)启用光照计算。 为了构建3D模型,我们需要使用OpenGL的几何构造函数,如glBegin和glEnd,定义物体的基本形状...
在“球的光照模型算法”这个项目中,你可能需要编写代码来生成球体的顶点数组,处理光照计算,以及设置OpenGL或Direct3D的状态。此外,优化光照计算,例如使用着色器程序,可以提高性能并实现更复杂的光照效果。 总...
作者王贞东、马小虎和潘志庚分别来自苏州大学计算机科学与技术学院和浙江大学计算机辅助设计与图形学国家重点实验室,他们提出了一种新的实时光照计算算法,以实现虚拟与实际场景在复杂环境光源下的无缝融合。...
6. 着色器:OpenGL中的顶点着色器和片段着色器用于处理光照计算。 掌握这些基本的光照模型和OpenGL编程技术对于开发高质量的3D图形应用至关重要,尤其是在手机这样的移动平台上,考虑到性能限制,优化光照模型的...
光照计算涉及到漫反射、镜面反射和环境光等几个方面,这些因素决定了物体表面颜色的最终呈现。 在描述中提到的“两个物体”,可能是指两个不同的3D模型,如立方体或者球体。每个物体的表面由多个多边形组成,每个...