简介:本项目为计算机图形学的实践课程,侧重于教授学生如何在C++ MFC框架内实现球体的光照模型算法。通过使用VC6.0开发环境编写和调试代码,学生将理解并掌握环境光、漫反射光和镜面反射光三大光照成分的计算方法。课程设计结合《计算机图形学基础教程》,注重理论知识与实践技能的结合,以加深对计算机图形学中光照模型的理解。
1. 光照模型基础与原理
1.1 光照模型的重要性
在计算机图形学中,光照模型是渲染逼真三维场景不可或缺的元素之一。它负责模拟现实世界中光线如何影响物体表面的视觉呈现。光照模型不仅关系到物体的明暗效果,还影响到质感、深度和空间关系的表达。通过理解光照模型的基本原理,开发者可以创造出更加生动和真实感强的虚拟环境,增强用户的沉浸式体验。
1.2 光照模型的基本组成部分
光照模型主要由几个关键成分构成:环境光(Ambient Light)、漫反射光(Diffuse Reflection)和镜面反射光(Specular Reflection)。环境光代表着场景中无处不在的光线,通常用于模拟光线的散射和间接照明。漫反射光则反映了光线如何从表面均匀散射,它与观察角度无关,是表面粗糙度和材质属性的体现。镜面反射光是指光线从平滑表面反射形成的亮点,它随观察角度变化而变化,是物体光泽和高光效应的主要来源。理解这些成分对于开发者构建光照模型来说至关重要。
1.3 光照模型的数学基础
光照模型的实现需要借助数学工具来表达上述物理现象。例如,Phong光照模型使用环境光、漫反射和镜面反射三个分量来计算像素点的颜色值。每个分量都有自己的数学表达式,比如漫反射光的计算公式通常基于朗伯余弦定律,而镜面反射则使用Blinn-Phong模型或者Cook-Torrance模型等更高级的物理公式。掌握这些数学知识能够帮助开发者更精确地控制光线的行为,从而实现更高质量的渲染效果。
2. 环境光的计算实现
2.1 环境光的理论基础
2.1.1 环境光的定义和作用
环境光(Ambient Light)是光照模型中的一个重要组成部分,它代表了场景中无法直接追踪来源的光,通常用于模拟间接光效,如散射光。在现实世界中,光线在场景中多次弹射,会在一定程度上均匀照亮表面,即使这些表面无法直接看到光源。环境光对场景的贡献是均匀的,它不会产生阴影,也不依赖于观察者或光源的位置。
环境光的主要作用是为场景提供基础照明,增加场景的整体亮度,使得在没有直接光照的部分也能显示出来,避免出现完全的黑色区域。它有助于在全局光照计算中保持图像的连贯性。
2.1.2 环境光模型的数学表示
在图形学中,环境光通常用以下简化的模型表示:
[ I_{ambient} = K_{a} \times I_{a} ]
其中: - ( I_{ambient} ) 是计算出的环境光强度。 - ( K_{a} ) 是材质对环境光的反射系数,一般是一个介于0到1之间的值。 - ( I_{a} ) 是环境光的颜色和强度,通常是一个常数,表示为RGB值。
这个模型假定环境光是均匀且各向同性的,意味着它在场景中的所有点和所有方向都是相同的。
2.2 环境光的计算方法
2.2.1 简单环境光模型的实现步骤
为了在渲染中实现环境光效果,我们可以遵循以下步骤:
- 定义环境光的颜色和强度,这可以是预设的值,也可以从环境光光源获得。
- 为每个渲染的几何体(如多边形)上的每个顶点计算环境光的贡献。
- 将顶点着色器中的环境光贡献传递到片元着色器。
- 在片元着色器中,根据材质属性和环境光的颜色和强度,计算出最终的像素颜色。
具体的代码实现可能如下所示:
// 顶点着色器代码片段
varying vec3 vAmbientLighting;
void main() {
// 假设这里已经计算出了顶点的世界坐标和法线向量等信息
// 之后计算环境光贡献
vAmbientLighting = ambientLightIntensity * ambientLightColor;
// 进行顶点位置变换等其他必要的计算
gl_Position = ...
}
// 片元着色器代码片段
varying vec3 vAmbientLighting;
uniform vec3 materialAmbient;
void main() {
// 根据材质属性和环境光强度计算像素颜色
vec3 color = vAmbientLighting * materialAmbient;
gl_FragColor = vec4(color, 1.0);
}
2.2.2 环境光参数的调整技巧
环境光参数的调整对最终渲染效果有着显著的影响。调整环境光强度时,通常需要在保持场景整体亮度不变的前提下,对不同物体的材质属性进行权衡。调整环境光颜色时,需要考虑其对场景整体氛围的影响。
为了获得更加逼真的效果,可以使用色调映射(Tone Mapping)技术,调整图像的亮度分布,使场景在不同光照条件下都有良好的视觉效果。调整时,可以通过改变( I_{a} )或者( K_{a} )的值来进行。例如,在较暗的场景中,可以增加( I_{a} )的值,使得暗部区域的细节能够被更好地保留。
2.3 环境光对渲染效果的影响
2.3.1 环境光强度对场景亮度的影响
环境光强度是控制渲染场景总体亮度的关键参数。如果环境光强度过高,会使得场景看起来过于明亮,从而丧失细节的对比度和深度;反之,如果强度过低,则会造成场景过于暗淡,导致细节丢失,甚至在某些区域出现“剪影”效果。
因此,需要找到一个合适的环境光强度平衡点,使得场景整体亮度适中,既可以表现出丰富的细节层次,又能够保持整体的视觉协调性。在不同的场景中,环境光的强度调整要根据实际的光照环境和设计意图来灵活控制。
2.3.2 环境光颜色对渲染氛围的作用
环境光的颜色在渲染中起到了非常重要的作用,它能够影响场景的情绪和氛围。例如,在一个温暖的场景中,我们可以增加环境光的暖色调,如增加红色和黄色的成分;而在一个冷色调的场景中,可以增加蓝色或绿色的成分,使场景看起来更加冷峻或科幻。
环境光颜色的选择应该与场景中的其他光源颜色相协调,并且与场景的主题相匹配。例如,在森林场景中,环境光可以带有绿色调,以模拟光线穿过树叶的散射效果。在城市夜景中,环境光则可以偏向于冷白色,以体现人造光源的氛围。
为了调整环境光的颜色,可以修改环境光的RGB值。例如,在着色器中设置不同的环境光颜色:
uniform vec3 ambientLightColor = vec3(0.1, 0.1, 0.1); // 默认为中性灰色
通过改变 ambientLightColor
的值,就可以调整环境光的颜色。这样的调整需要根据实际效果不断进行微调,以达到最佳的视觉效果。
在以上章节中,我们对环境光的定义、模型和计算方法进行了深入的探讨,同时也演示了如何在渲染场景中实现和调整环境光来提升场景的整体氛围。这些知识是构建逼真光照效果的基础,对渲染人员来说是不可或缺的技能。
3. 漫反射光的计算实现
3.1 漫反射光的理论基础
3.1.1 漫反射光的定义和特性
漫反射光是指光线在非光滑表面上发生不规则反射的现象,其特点是光线向各个方向均匀地散射。不同于镜面反射,漫反射不依赖于观察者的位置,即在不同角度观察表面,其亮度和色彩相对一致。漫反射光在现实世界中几乎无处不在,比如纸张、墙壁、皮肤等非光泽表面。
漫反射光的特性使其成为真实感渲染中不可或缺的一部分。它在渲染中主要负责决定物体的固有色和基础亮度,其强度受光源强度、物体材质、观察角度等因素影响。理解漫反射光的基本特性对于进行三维渲染和模拟现实光照至关重要。
3.1.2 漫反射光模型的数学基础
漫反射的数学模型可以通过朗伯余弦定律来描述,其公式为:
Ld = N · L
其中, Ld
表示漫反射光的亮度, N
是表面法线向量, L
是指向光源的单位向量。点乘操作可以表示为两个向量的余弦值乘以它们各自的模长。该公式说明了漫反射光亮度与表面法线和光线方向的余弦成正比。
在实际计算中,我们通常还需要考虑光源的强度( Li
),因此漫反射光的计算公式可以扩展为:
I = k_d * Li * max(N · L, 0)
在这里, k_d
是材质的漫反射系数,用于控制物体颜色的强度,其范围通常在0到1之间。 max(N · L, 0)
函数确保当表面背对光源时,漫反射光的亮度为零,这符合现实世界的物理规律。
3.2 漫反射光的计算方法
3.2.1 漫反射光强度的计算公式
要计算漫反射光的强度,我们需要知道表面法线、光源方向以及材质的相关系数。通过上述数学模型,我们可以得到漫反射光强度的计算公式:
Ld = k_d * Li * max(0, N · L)
其中, max(0, N · L)
确保了当表面背对光源时,漫反射光的亮度不会被计算。在代码实现时,我们通常会将上述公式转化为向量操作,以便更高效地处理。
3.2.2 材质属性对漫反射的影响
材质属性包括漫反射系数、镜面反射系数、透明度等,这些属性共同决定一个物体在光照下的表现。在计算漫反射光时,材质的漫反射系数( k_d
)显得尤为关键,它直接决定了漫反射光的强度。
例如,一个具有高漫反射系数的材质会显得更加明亮,因为它能够反射更多的漫反射光。反之,一个低漫反射系数的材质则会显得比较暗淡。在渲染过程中,通过对材质属性的合理设置,可以模拟各种不同的材质效果,从而达到更真实的效果。
3.3 漫反射光在渲染中的应用
3.3.1 漫反射光与视点位置的关系
在渲染场景时,漫反射光计算与视点位置无关,因为漫反射光不依赖于观察者的具体位置。这一特性使得漫反射光的计算相对简单,便于在各种视角下保持一致性。
3.3.2 漫反射光在实际场景中的案例分析
漫反射光在渲染中的应用广泛,它构成了场景中大部分的非高光区域。例如,在一个室内场景中,墙壁和家具的光照效果很大程度上取决于漫反射光的处理。
以下是一个简单的漫反射光照模型计算的伪代码示例,用于说明其在实际渲染中的应用:
// 伪代码:计算漫反射光照
Vector3 ambientLight = getAmbientLight(); // 获取环境光
Vector3 diffuseLight = Vector3(0, 0, 0); // 初始化漫反射光
for each lightSource in lightSources {
Vector3 lightDirection = getLightDirection(lightSource);
Vector3 normal = getSurfaceNormal(surface);
float NdotL = max(0, dot(normal, lightDirection)); // 计算法向量与光源方向的点积
diffuseLight += lightSource.intensity * material.kd * NdotL; // 累加漫反射光强度
}
Vector3 finalColor = ambientLight + diffuseLight; // 最终颜色为环境光与漫反射光之和
在上述代码中,我们为每个光源计算了漫反射光,并将其与环境光相加得到最终的颜色。通过调整材质的漫反射系数和光源的强度,可以模拟出丰富多样的光照效果。实际渲染时,这些计算通常会集成到图形管线中,通过GPU进行高效处理。
通过漫反射光的计算和应用,开发者可以在渲染过程中模拟出逼真的光照效果,为用户提供沉浸式的视觉体验。
4. 镜面反射光的计算实现
4.1 镜面反射光的理论基础
4.1.1 镜面反射光的概念和原理
镜面反射是指光线在平滑表面发生的一种反射现象,它遵循反射定律,即入射角等于反射角。镜面反射的关键在于表面的平滑度,平滑表面可以产生清晰的反射图像。在光照模型中,镜面反射是创建光泽和反光效果的核心要素。它使得物体表面能够反射周围环境,增强了真实感。例如,一个抛光的金属球或水滴,其表面的光泽和反光部分,都是由于镜面反射的效果。
4.1.2 镜面反射光模型的关键参数
为了模拟镜面反射效果,通常会引入一些关键参数。最重要的参数之一是镜面反射系数(specular coefficient),它决定了表面反射光线的强度。另一个参数是光泽度指数(glossiness exponent),它决定了反射光斑的大小和边缘的锐利程度。这两个参数通常结合起来使用,以模拟不同材质的镜面反射特性。数学上,这些参数可以通过Phong反射模型、Blinn-Phong模型等来表达。
4.2 镜面反射光的计算方法
4.2.1 镜面反射光强度的计算方式
镜面反射光的计算方式在不同光照模型中有不同的实现。在Phong模型中,镜面反射光强度I_specular可以通过以下公式计算:
I_specular = K_spec * L_spec * max(N.V, 0)^glossiness
这里, K_spec
是材质的镜面反射系数, L_spec
是光源对镜面反射的贡献, N
是表面法线, V
是观察方向, glossiness
是光泽度指数。 max(N.V, 0)^glossiness
确保了只有当观察方向和反射方向接近时,才会有高的反射光强度。
4.2.2 镜面高光效果的实现技巧
为了实现镜面高光效果,需要精细控制光泽度指数。高光泽度表面会产生较小且集中的高光,而低光泽度表面则会产生较大且较模糊的高光。为了提高渲染效率,常常采用半球光源或环境光遮蔽技术来模拟间接的镜面反射效果。
此外,可以使用多种技术来优化镜面反射的计算过程。一种是通过图像空间的方法,比如屏幕空间环境光遮蔽(SSAO),以获得更加真实的环境光遮蔽效果。另外,也可以使用预计算的光照贴图来提高渲染性能,尤其是在静态或相对静态的场景中。
4.3 镜面反射光在渲染中的应用
4.3.1 镜面反射对场景光泽的影响
镜面反射对于整个场景光泽的影响至关重要。具有镜面反射特性的物体表面能够呈现出明暗分明的高光区域,使得这些物体的表面显得更为光滑和有光泽。例如,汽车的漆面或玻璃的反射特性,可以通过精确控制镜面反射参数来模拟。通过调整光泽度参数,可以模拟从粗糙到光滑的各种材质。
4.3.2 镜面反射在复杂光照场景中的案例
在复杂光照场景中,镜面反射计算会变得更加复杂。例如,在一个有多个光源和不同材质的室内场景中,各材质表面的镜面高光应该反映出所有光源的综合效果。在高级渲染技术如路径追踪中,镜面反射的计算会考虑到光线多次弹射后的影响,通过递归方式实现更真实的效果。
在实际操作中,使用3D建模软件时,可以通过材质编辑器设置镜面反射参数,如下图所示的一个材质编辑器界面示例:
graph TB
A[材质编辑器] --> B[基础属性]
A --> C[贴图设置]
A --> D[光照设置]
B --> E[镜面反射系数]
B --> F[光泽度指数]
C --> G[漫反射贴图]
C --> H[法线贴图]
D --> I[环境光]
D --> J[镜面反射]
表格也常用于展示不同材质的镜面反射参数对比,例如:
| 材质类型 | 镜面反射系数 | 光泽度指数 | |----------|--------------|------------| | 金属 | 高 | 高 | | 漆面 | 中 | 中 | | 玻璃 | 低 | 非常高 |
在实际渲染过程中,还可以通过编写代码来动态调整这些参数。以下是一段示例代码,它展示了如何在渲染循环中计算镜面反射:
for (each object in scene) {
for (each light in scene) {
// 计算镜面反射
float specular = 0.0f;
if (dot(N, R) > 0) {
specular = pow(dot(N, R), object.glossiness);
specular *= object.specularCoefficient;
}
// 累加来自光源的镜面反射贡献
object.color += specular * light.specularColor * light.intensity;
}
}
在上述代码中, N
是表面法线, R
是镜面反射方向, dot(N, R)
计算法线和反射方向的点积。如果这个值大于0,则表示表面在该方向上有镜面反射发生。随后,通过 pow
函数来调整光泽度指数,并乘以镜面反射系数和光源的镜面颜色和强度,来计算最终的镜面反射颜色。
通过上述的理论基础、计算方法和渲染应用的详细解释,我们可以深入理解如何在3D渲染中实现镜面反射效果。掌握这些知识对于制作高质量的视觉效果至关重要。
5. C++ MFC在图形学中的应用
5.1 MFC图形界面设计基础
5.1.1 MFC框架概述及结构特点
MFC(Microsoft Foundation Classes)是一个基于C++的类库,旨在简化Windows平台上应用程序的开发。它封装了Windows API,提供了一种更面向对象的方式来编写程序。MFC拥有丰富的类库和框架结构,其核心在于一个由文档-视图结构组成的架构,它为开发者提供了一种高效的方式来管理应用程序的数据和显示。
MFC框架的主要特点包括: - 消息映射机制 :MFC采用消息映射机制处理Windows消息,这是MFC框架的核心技术之一。开发者只需要重写特定的消息处理函数,而无需直接操作消息队列或响应消息。 - 文档-视图架构 :这种架构允许程序将数据(文档)与数据显示(视图)分离,提高了代码的重用性和模块化。 - 资源管理 :MFC通过资源文件(如对话框、菜单、位图等)来管理界面元素,简化了资源的创建和管理过程。 - 继承和封装 :MFC提供了大量继承自CObject的类,通过封装和继承大大简化了图形界面编程的复杂性。
5.1.2 MFC中图形绘制的基本方法
在MFC中进行图形绘制,主要可以通过以下几个途径: - OnDraw(CDC* pDC) :这是一个由CView派生类继承的函数,在视图需要重绘时由框架调用。通过CDC对象提供的绘图函数,可以在客户区绘制图形。 - CPaintDC :这是一种特别的设备上下文类,当视图需要进行显示更新时创建。它在OnDraw函数中被创建,在该函数返回时自动被删除。 - GDI对象 :GDI(图形设备接口)对象如CPen(画笔)、CBrush(画刷)、CFont(字体)等,用于在CDC上进行图形绘制。
举例来说,以下是一个简单的OnDraw方法实现,使用CPen画笔绘制一条线:
void CMyView::OnDraw(CDC* pDC)
{
CPen pen(PS_SOLID, 2, RGB(0,0,0)); // 创建黑色的实线画笔,宽度为2
CPen* pOldPen = pDC->SelectObject(&pen); // 选择画笔到设备上下文
// 在这里绘制图形
pDC->MoveTo(10, 10); // 移动到起始坐标
pDC->LineTo(100, 100); // 绘制一条线到(100,100)
// 清理工作
pDC->SelectObject(pOldPen); // 恢复之前的画笔
pen.DeleteObject(); // 删除创建的GDI对象
}
在上述代码中,我们首先创建了一个黑色的实线画笔,然后将其选入设备上下文中,执行了简单的绘图命令后,又将画笔替换回原来的状态,并删除了我们创建的画笔对象。
5.2 MFC与图形学的结合
5.2.1 MFC在图形渲染中的应用实例
MFC在图形渲染上的应用可以通过创建一个简单图形渲染程序来体现。例如,一个能够响应用户输入并绘制图形的程序,可以使用MFC框架来完成。
下面是一个简单的程序示例,它创建了一个窗口,并允许用户通过点击窗口来绘制圆形:
class CDrawCircleView : public CView
{
protected:
virtual void OnLButtonDown(UINT nFlags, CPoint point);
};
void CDrawCircleView::OnLButtonDown(UINT nFlags, CPoint point)
{
CPen pen(PS_SOLID, 2, RGB(0,0,255)); // 创建蓝色的实线画笔
CPen* pOldPen = GetDC()->SelectObject(&pen);
// 创建圆刷用于填充圆形
CBrush brush(RGB(0, 255, 255)); // 青色
CBrush* pOldBrush = GetDC()->SelectObject(&brush);
// 使用画笔和圆刷绘制圆形
GetDC()->Ellipse(CRect(point.x-25, point.y-25, point.x+25, point.y+25));
// 恢复原来的对象
GetDC()->SelectObject(pOldPen);
GetDC()->SelectObject(pOldBrush);
pen.DeleteObject();
brush.DeleteObject();
}
此代码段展示了如何捕获鼠标左键点击事件,并在用户点击的位置绘制一个圆形。这里使用了GDI对象来实现绘制工作,展示了MFC在图形渲染中的基本应用。
5.2.2 MFC对图形学算法的支持和优化
MFC作为高层的API封装,对于一些基础图形学算法有着直接的支持,例如绘图、图形变换等。然而,对于更高级的图形学算法,如光照模型、阴影生成、反走样等,MFC可能需要更多的自定义和扩展。
MFC可以通过以下方式优化图形学算法: - 扩展类库 :可以定义新的类或者继承现有的MFC类,以支持复杂的图形学算法。 - 组件化 :将复杂的算法封装成独立的组件,可重用且易于维护。 - 多线程优化 :利用MFC的多线程特性,将耗时的图形计算放在后台线程进行,以避免阻塞UI响应。
下面是一个简单的例子,说明如何利用MFC中的定时器和多线程进行简单的动画渲染:
// 定义一个变量来记录动画的帧
int frame = 0;
void OnTimer(UINT_PTR nIDEvent)
{
static CRect rect;
GetClientRect(&rect); // 获取客户区大小
// 每次调用OnTimer时重绘视图
InvalidateRect(&rect);
// 更新帧动画
frame++;
}
UINT MyThread(LPVOID lpParam)
{
while (true)
{
// 在这里执行一些耗时的图形计算
// 比如更新动态场景中的对象位置
// 使用PostMessage向主线程发送消息,更新UI
PostMessage(WM_USER_UPDATE_ANIMATION);
// 等待一段时间再进行下一次循环
Sleep(33); // 大约30FPS
}
}
此段代码演示了如何使用MFC的定时器和多线程来创建一个简单的动画渲染循环,定时器用于触发展示的更新,多线程用于在后台执行计算密集型任务。
通过MFC的应用实例和优化,我们看到了MFC在图形学应用中强大的灵活性和扩展性。MFC的图形绘制功能不仅可以实现基础的UI设计,还可以通过编程扩展实现更复杂的图形学算法,这对于希望在Windows平台上进行图形学应用开发的程序员来说,是一个非常有用的工具库。
6. VC6.0环境下的源码编写与调试
在本章中,我们将详细探讨在VC6.0环境下如何进行源码编写与调试。VC6.0作为一款老牌但功能强大的开发工具,它集成了代码编写、编译、调试等多种开发所需的功能。本章节将为读者展示如何利用VC6.0编写高效的源码,并通过各种调试技巧来优化和测试代码。
6.1 VC6.0开发环境配置
6.1.1 VC6.0安装与基本设置
首先,我们要了解如何安装Visual C++ 6.0并进行基本的设置。VC6.0的安装过程是直接的,通常只需按照安装向导的指示进行,选择需要安装的组件。安装完成后,主要的设置工作通常集中在项目设置和开发环境个性化方面。例如,开发者可以根据个人喜好设置代码编辑器的颜色方案,以提高代码的可读性。
6.1.2 VC6.0中的项目管理和编译过程
在VC6.0中创建和管理项目,是开发流程中的重要一步。开发者需要通过File -> New对话框来创建新的项目,并选择合适的项目类型,例如Win32 Application或Win32 Console Application等。项目创建完毕后,开发者应熟悉项目属性的设置,这包括编译器选项、链接器选项以及资源设置等。这一步对于确保代码能够正确编译和链接至关重要。
6.2 源码编写与调试技巧
6.2.1 源码结构设计与代码风格规范
在编写源码之前,合理的结构设计和遵守代码风格规范可以大幅提高代码的可维护性和可读性。源码结构设计包括模块划分、函数划分等,而代码风格规范则包括命名规则、缩进风格等。这些在团队协作中尤为重要,可以帮助团队成员快速理解代码结构和逻辑,降低沟通成本。
6.2.2 调试工具的使用和性能分析
使用VC6.0的调试工具可以检查代码执行中的各种问题,如变量值、内存使用情况、断点的设置等。性能分析工具则能帮助开发者分析程序运行性能,找出瓶颈所在。正确使用这些工具可以大幅度提高开发效率和代码质量。
6.3 光照模型算法的代码实现与测试
6.3.1 光照模型算法的代码解析
在VC6.0环境下,开发者可以将前几章讨论的光照模型理论转化为实际的代码。例如,可以使用C++编写环境光、漫反射光、镜面反射光的计算函数,并将这些函数应用于3D场景的渲染。代码中会包含各种数学计算,如向量运算、矩阵运算等,这些都是实现光照模型不可或缺的部分。
6.3.2 算法在VC6.0环境下的测试与优化
最后,算法的测试和优化是开发流程中不可忽视的部分。开发者需要在VC6.0环境下运行代码,对光照效果进行观察,并根据需要调整算法参数。性能测试也是必要的,通过性能分析工具可以发现并优化潜在的性能瓶颈。
在本章中,我们了解了如何在VC6.0环境下进行源码编写与调试的详细流程,以及如何将光照模型算法转化成代码并进行测试与优化。通过阅读本章内容,开发者可以更好地利用VC6.0这一成熟工具,提高开发效率和代码质量。
简介:本项目为计算机图形学的实践课程,侧重于教授学生如何在C++ MFC框架内实现球体的光照模型算法。通过使用VC6.0开发环境编写和调试代码,学生将理解并掌握环境光、漫反射光和镜面反射光三大光照成分的计算方法。课程设计结合《计算机图形学基础教程》,注重理论知识与实践技能的结合,以加深对计算机图形学中光照模型的理解。