Computer Graphics
2024-2025 计算机图形学
计算机图形学 第一讲
课程介绍与概要
课程介绍
计算机图形学是研究如何利用计算机进行图形的表示、计算、处理与显示的科学学科。核心任务包括:
- 建模(Modeling):如何在计算机中表示三维物体及场景?
- 渲染(Rendering):如何将三维几何模型绘制出来,产生视觉效果?
- 动画(Animation):如何描述物体随时间变化的状态?
- 交互(Interaction):如何通过人机交互完成用户所希望的任务?
课程内容大纲
课程分为三个阶段:
- 相关知识背景(1-3周):包括引言、历史与应用、渲染管线、OpenGL 编程基础。
- 计算机图形学基础(4-13周):光栅化、几何变换、视角、曲线及曲面建模等。
- 进阶与扩展课题(14-17周):网格处理、光影、全局光照、纹理映射、蒙特卡洛渲染、神经网络渲染等前沿技术。
课程评分标准
- 编程作业:占65%,重点考察完成度、编程规范及美观等。
- 期末大作业:占20%,需要完成报告及现场展示。
- 科技论文阅读:占10%,通过阅读前沿论文加深理解。
- 出勤及小测:占5%。
计算机图形学的基本任务
建模(Modeling)
建模的核心是如何在计算机中表示三维物体和场景。常见的建模方式包括:
- 实体几何构造(Constructive Solid Geometry,CSG):通过几何运算生成新的形体。
- 网格(Mesh):通过记录点的坐标及其连接关系,近似表示连续曲面,如著名的 Stanford bunny 。
- 样条曲线与曲面:用于工业造型的标准。
- 体数据(Volume):常用于标量场的表示,如医学成像中的CT数据。
- 过程式建模:基于规则和语法生成模型,适合具有重复特征的几何物体(如树木)。
- 三维场景的神经网络表示:例如神经辐射场(NeRF)。
- 手工建模:利用软件工具手动构建模型。
- 三维扫描:通过扫描真实物体生成三维模型。
渲染(Rendering)
渲染是将三维几何模型转换为二维图像的过程,常见的渲染目标包括:
- 真实感渲染(Photorealistic Rendering):通过物理模拟实现逼真的光影效果,通常用于电影特效等高质量场景。如电影《Monsters University》中的渲染,使用了24,000核的渲染农场,每帧渲染耗时29小时。
- 实时渲染(Interactive Rendering):在数毫秒内生成图像,通常用于游戏等追求实时反馈的应用。
- 非真实感渲染(Non-photorealistic Rendering):风格化渲染,用于艺术作品或示意图。
动画(Animation)
动画是使几何模型随时间变化的过程。常见手段包括:
- 手动关键帧动画:通过定义关键帧控制物体运动。
- 行为模拟:通过物理规则模拟物体在环境中的行为,如流体或刚体的运动。
- 物理模拟:通过物理方程模拟真实世界中的运动效果,如布料、烟雾等。
- 动作捕捉(Motion Capture):通过捕捉实际人物的动作并映射到虚拟角色。
交互(Interaction)
交互使用户能够控制物体的内容、结构、外观,并产生实时的视觉反馈。典型应用包括:
- 输入设备:如鼠标、手绘笔、多点触控设备等。
- 输出设备:如显示器、打印机等。
最早的交互式图形系统为 Sketchpad,由 Ivan Sutherland 于1963年提出,奠定了现代交互式图形系统的基础。
计算机图形学的扩展
可视化(Visualization)
可视化是计算机图形学的一个分支,主要用于数据的图形化表现,帮助用户从数据中获取有用信息。常见的可视化类别包括:
- 科学可视化:如流场可视化,通过 LIC(Line Integral Convolution)等技术表现复杂数据。
- 信息可视化:如通过图表、关系图表现复杂信息。
- 可视分析:通过人机交互对数据进行分析。
设计(Design)
设计是计算机图形学的另一应用领域,涉及到工业设计、交互设计和通信设计等。常用工具包括 CAD(计算机辅助设计)和 HCI(人机交互)系统。
参考资料
推荐教材
- E. Angel, D. Shreiner: Interactive Computer Graphics — A Top-down Approach Using OpenGL (第七版)
- D. Hearn et al.: Computer Graphics with OpenGL (第四版,2014年)
- J. Kessenich et al.: OpenGL Programming Guide (第九版,2016年)
在线资源
- OpenGL-Song Ho Ahn: http://www.songho.ca/opengl/
- NeHe Productions: http://nehe.gamedev.net/
- OpenGL-tutorial: http://www.opengl-tutorial.org/
渲染软件
- Pixar’s RenderMan:著名的电影级渲染软件,广泛用于高质量的照片级渲染。
拓展阅读建议
- 神经网络与图形学结合:如 NeRF(Neural Radiance Fields)等技术代表了图形学领域的前沿方向。
- GPGPU(通用图形处理器计算):利用 GPU 的并行处理能力加速渲染、模拟等任务。
- 实时光影效果:深入研究实时光影渲染技术,如 Ray Tracing 在游戏中的应用。
计算机图形学 第二讲
现代计算机图形学的发展
硬件变革:显卡运算性能的爆炸性增长
随着显卡(GPU)运算性能的快速提升,计算机图形学迎来了巨大发展。显卡的发展主要依赖于以下几个因素:
- 摩尔定律:由英特尔创始人之一 戈登·摩尔 提出,集成电路上可容纳的晶体管数目大约每两年翻一倍。这意味着计算机硬件的性能也会随之提升。然而,摩尔定律也面临瓶颈,晶体管数量的增加并不意味着频率的提升,未来摩尔定律能持续多久也存在不确定性。
- CPU 与 GPU 性能的对比:GPU 的并行计算能力远超 CPU,在处理图形渲染、模型计算等任务时显著加速。
GPU 的通用计算:GPGPU
GPGPU(General-Purpose computing on Graphics Processing Unit)是将 GPU 从只处理图形任务扩展到通用计算的方案。GPGPU 的优势在于:
- 高度并行化:GPU 拥有大量计算核心,能够同时处理大量数据。
- 图形绘制流程的简化:如通过 Vertex Shader 和 Fragment Shader 进行图形的渲染,这些步骤可以通过用户编写的 shading language(着色语言)进行自定义。
常见的 GPGPU 应用包括:
- 计算机视觉:如 OpenCV 库的加速。
- 深度学习:如 TensorFlow 框架中,利用 GPU 处理大量并行的计算任务。
输入输出设备的丰富化
现代计算机图形学不仅依赖于 GPU 的提升,还受益于输入输出设备的丰富化:
- 输入设备:包括传统的鼠标、手写笔、多点触控等设备,甚至包括体感设备(如 Xbox Kinect、Leap Motion)等。
- 输出设备:从台式机和笔记本电脑的显示屏,到智能手机、智能手表及 3D 虚拟现实设备(如 Oculus Rift、Google Cardboard、Microsoft Hololens)等。
计算机图形学的发展史
早期发展(1950-1970年代)
- 1950年代:MIT 开发了首个可视显示单元(VDU),CalComp 推出了滚筒绘图仪,Gerber 公司开发了平板绘图仪,奠定了早期计算机图形学的硬件基础。
- 1960年代:
- Spacewar:第一个计算机游戏,由 MIT 学生 Steve Russell 开发。
- Sketchpad 系统:由 Ivan Sutherland 在其博士论文中提出,成为第一个交互式图形系统。
- CAD(计算机辅助设计):由 MIT 教授 Steven Anson Coons 提出,CAD 系统在60年代末得到了广泛应用,尤其是 Bezier 曲线的发明对现代 CAD 产生了深远影响。
- 1970年代:光栅化图形算法快速发展,标准化进程加速,出现了诸如 GKS、PHIGS 等图形标准。此外,Bouknight 提出了最早的光反射模型,Phong 着色模型的提出奠定了现代图形渲染的基础。
计算机图形学的里程碑(1980年代至今)
1980年代:
- 光线追踪(Ray Tracing)和 辐射度(Radiosity)算法的提出使得图形渲染质量大幅提升,尤其是光线追踪技术可以模拟现实世界中的光影效果。
- 专业图形工作站的出现推动了图形学的发展,但随着硬件的普及,越来越多的图形处理工作由 GPU 和通用硬件完成。
1990年代:
- 建模技术:如网格、细分曲面、隐式曲面(Implicit Surface)等建模技术逐渐成熟。
- 渲染技术:基于图像的渲染、体渲染、点基渲染等新技术出现,进一步丰富了图形学的表现形式。
2000年后:
- 3D 扫描技术:通过扫描真实物体生成三维模型的技术迅速发展。
- GPU 并行编程:随着 GPU 的性能提升,计算机图形学任务越来越依赖于并行计算。
- 深度学习:神经网络的兴起推动了图形学领域的智能化发展,如神经渲染技术的应用。
新兴趋势
- 体感设备:如微软的 Kinect,支持通过手势和身体动作进行交互。
- 3D 打印:3D 打印技术的普及使得虚拟设计与实际制造之间的距离越来越短。
- 虚拟现实(VR):如 Cyberith Virtualizer,提供更加沉浸式的虚拟现实体验。
- 神经辐射场(NeRF):利用神经网络对三维场景进行建模和渲染,成为图形学领域的前沿技术。
计算机图形学的应用
计算机图形学的应用领域非常广泛,涉及多个行业和技术领域:
电影与动画
- 电影特效:计算机图形学在电影中的应用包括复杂的动画生成和物理仿真,尤其是动画电影和科幻电影中。
- 动作捕捉:通过捕捉真人的动作并映射到虚拟角色,广泛用于电影和游戏中的角色动画。
游戏
- 实时渲染:游戏中广泛应用实时渲染技术,结合光影效果、物理引擎等,提升游戏的视觉体验。
图像与设计
- 广告与艺术:计算机图形学已成为广告设计和艺术创作的重要工具,通过数字手段创造出逼真的视觉效果。
- UI 设计:随着用户界面设计的复杂化,计算机图形学帮助设计出更加人性化和美观的用户界面。
训练与模拟
- 仿真系统:如飞行模拟器、驾驶训练系统,利用计算机图形学技术提供高度逼真的训练环境。
地理科学与医学影像
- 地理信息系统(GIS)和数字城市:计算机图形学在地理科学中的应用包括几何对齐算法、数字地球和数字城市的构建。
- 医学影像:通过三维重建技术,医学图像可以在计算机上进行可视化分析,帮助医生更准确地诊断和治疗。
计算机辅助设计(CAD)
- CAD 已广泛应用于多个行业,尤其是在工业设计和建筑设计中,计算机图形学帮助设计师创建精确的三维模型。
如何学习计算机图形学
学习动机
- 广泛应用:计算机图形学在电影、游戏、教育、科学等多个领域有着广泛的应用,且市场需求巨大。
- 兴趣驱动:学习计算机图形学可以发挥个人的创造力,通过编程和技术手段绘制出绚丽的图像。
学习计算机图形学的必备条件
- 跨学科知识:需要掌握数学(几何、线性代数)、物理学、计算机科学以及艺术设计等多学科的知识。
- 好奇心与创造力:对未知的探索欲望和对技术的追求是学习计算机图形学的重要动力。
- 实践能力:通过编程实践(如 C++、OpenGL)掌握图形学的基本算法和技术。
课程目标
通过本教程,你将会学习到:
- 基础计算机图形学算法:如几何处理、真实感渲染的算法与数据结构。
- OpenGL 编程:掌握图形编程的基本技术,了解如何实现从建模到渲染的完整过程。
计算机图形学的前沿与资源
国际会议
- ACM SIGGRAPH:计算机图形学领域最重要的国际会议之一,致力于展示最新的图形学技术和研究成果。
- Eurographics、Pacific Graphics、Chinagraph:其他重要的国际会议,涵盖了几何处理、渲染、动画等多个方向。
相关期刊
- ACM Transactions on Graphics
- IEEE Transactions on Graphics and Visualization
- Computer Graphics Forum
- Computer-aided Design
- 中国图象图形学报
这些期刊汇集了图形学领域的最新研究成果,是学习和了解前沿技术的重要资源。
在线资源
- NVIDIA GameWorks™:提供丰富的图形学开发示例和工具。
- CGAL:计算几何算法库。
- OpenMesh:用于三维网格处理的开源库。
- Blender:开源的三维建模与渲染工具。
- Unity 3D:广泛用于游戏开发的引擎,具备强大的图形渲染能力。
以上资源为学习和实践计算机图形学技术提供了强有力的支持。
通过第二讲的学习,我们了解了计算机图形学的发展历程、技术变革和广泛应用,同时也为后续的课程学习奠定了理论和技术基础。
计算机图形学 第三讲
OpenGL 编程入门
OpenGL 是什么?
OpenGL,即 Open Graphics Library,是用于渲染 2D 和 3D 矢量图形的跨平台、跨语言的应用程序接口(API)。它的主要特性包括:
- 跨平台:可以在不同平台上使用,如 Windows、Linux、macOS 等。
- 跨语言:支持多种编程语言,如 C、C++、Python 等。
- 硬件依赖:虽然 OpenGL 是跨平台的,但其具体实现依赖于硬件厂商,通常由显示设备制造商提供。
- 渲染功能:OpenGL 主要用于图形渲染,不提供音频或窗口管理等功能,需要配合其他工具库(如 GLUT)使用。
OpenGL 的发展过程
- 1992年,由 Silicon Graphics Inc. (SGI) 领导成立 OpenGL 架构审查委员会(ARB),负责 OpenGL 规范的维护和扩展。
- 2006年,OpenGL ARB 将控制权移交给 Khronos Group。
- OpenGL 的最新版本为 OpenGL 4.6,发布于2017年。
OpenGL 相关的其他选择
除了 OpenGL 之外,还存在其他图形渲染解决方案,如:
- DirectX:主要用于 Windows 平台。
- NVIDIA CUDA:尽管不是图形库,但提供了使用 GPU 进行高性能计算的开发环境。
- Vulkan:由 Khronos Group 开发,继承了 OpenGL,但不再兼容旧版本。
OpenGL 能做什么?
OpenGL 的核心功能是图形渲染,具体来说,它可以:
- 定义物体形状:如顶点、几何形状等。
- 定义材料属性和光照:控制物体的颜色、光照反射等。
- 转换物体到屏幕坐标系:通过光栅化(Rasterization)将几何体转换为屏幕空间中的像素。
- 计算每个片段(Fragment)的颜色:混合每个片段的颜色,最终生成屏幕上的像素。
OpenGL Utility Toolkit(GLUT)
GLUT 是一个实用工具包,虽然不是 OpenGL 的官方组成部分,但它提供了系统级别的输入输出功能。GLUT 提供以下功能:
- 窗口管理:定义窗口,控制窗口大小,捕获键盘和鼠标事件。
- 基本几何体绘制函数:如正方体、球体、Utah 茶壶等,支持实心和线框模式。
- 菜单功能:可以为应用程序添加简单的菜单结构。
GLUT 安装
对于 Windows 平台,可以按照以下步骤安装 GLUT:
- 下载 GLUT 库(推荐使用 FreeGLUT)。
- 将
glut.dll
文件复制到{Windows DLL dir}/glut32.dll
。 - 将
glut.lib
文件复制到{VC++ lib path}/glut32.lib
。 - 将
glut.h
文件复制到{VC++ include path}/GL/glut.h
。 - 在代码中添加
#include <GL/glut>
。
在实际开发中,推荐使用更现代的工具,如 Qt,并提供了相应的程序模板。
OpenGL 是如何工作的?
OpenGL 的状态机模型
OpenGL 是一个 状态机,其工作原理是通过函数调用设置内部状态变量(如当前颜色、光源位置等)。每个状态变量都有初始值,且一旦设置状态,直到显式改变之前,状态保持不变。
OpenGL 渲染管线(Pipeline)
OpenGL 的渲染过程可以用以下简易管线(pipeline)表示:
- Display List:存储预编译的 OpenGL 命令列表,不能修改,执行速度快。
- Evaluator:处理曲线和曲面的计算,将控制点描述的曲线/曲面离散化为顶点。
- Per-Vertex Operations:基于顶点进行的操作,如空间变换。
- Primitive Assembly:将顶点组装成图元(如点、线、三角形等)。
- Rasterization:将图元转换为片段(fragment),每个片段对应屏幕上的一个像素。
- Per-Fragment Operations:对每个片段进行颜色和深度计算,最终确定屏幕上每个像素的颜色。
- Frame Buffer:保存渲染结果,并传输到屏幕进行显示。
OpenGL 中的函数分类
OpenGL 的函数可以分为以下几类:
- 图元:定义基本的几何体,如点、线、三角形。
- 属性:设置图元的属性,如颜色、材质等。
- 变换:控制图元的空间变换,如平移、旋转、缩放。
- 输入与控制:由 GLUT 等工具库提供,用于处理窗口、鼠标、键盘等输入事件。
- 查询:查询 OpenGL 的状态或属性。
OpenGL 程序结构简介
OpenGL 程序的基本文件需求
为了编写一个 OpenGL 程序,通常需要以下文件:
- 头文件:
#include <GL/gl.h>
:OpenGL 核心头文件。#include <GL/glu.h>
:OpenGL 实用库头文件。#include <GL/glut.h>
:GLUT 头文件。
- 库文件:
- 静态库:
opengl32.lib
、glu32.lib
、glut32.lib
,需要将这些库放置在编译器的 lib 目录下。 - 动态库:
opengl32.dll
、glu32.dll
、glut32.dll
,需要将这些动态库放置在系统目录中(如c:/Windows/System32
)。
- 静态库:
OpenGL 程序的基本结构
OpenGL 程序通常是事件驱动编程,其基本结构如下:
1. Configure & Open Window |
每个 OpenGL 程序通常包含一个无限循环,等待用户输入事件(如鼠标点击、键盘按下)并执行相应的渲染操作。
OpenGL Hello World 示例
下面是一个简单的 OpenGL “Hello World” 示例,展示了如何绘制一个基本窗口并渲染内容:
|
代码讲解:glutInit()
:初始化 GLUT 库。glutInitDisplayMode()
:设置显示模式,GLUT_SINGLE
表示单缓冲,GLUT_RGB
表示使用 RGB 颜色模式。glutInitWindowSize()
:设置窗口大小(400x300)。glutInitWindowPosition()
:设置窗口在屏幕上的初始位置。glutCreateWindow()
:创建一个名为 “Hello World” 的窗口。glutDisplayFunc()
:注册一个显示回调函数,当窗口需要重绘时调用。glutMainLoop()
:进入 GLUT 主循环,等待事件。
OpenGL 回调函数
OpenGL 使用回调函数处理用户交互事件,如鼠标点击、键盘输入等。回调函数允许我们在事件发生时调用自定义的处理函数。
回调函数工作原理:
- 主线程等待事件(如鼠标点击、键盘按下)。
- 当事件发生时,系统调用注册的回调函数,并将特定事件的信息传递给它。
GLUT 回调函数示例
以下是 GLUT 回调函数的示例代码,展示如何处理键盘和鼠标事件:
|
代码讲解:keyboardCB()
:处理键盘事件,当按下 ‘a’ 键时输出相应信息。mousebutton()
:处理鼠标事件,当鼠标左键按下时输出点击的坐标。glutKeyboardFunc()
和 glutMouseFunc()
:注册键盘和鼠标回调函数。
OpenGL 基本概念与语句
OpenGL 上下文(Context)与视口(Viewport)
上下文:OpenGL 的 context 存储与当前 OpenGL 实例相关的所有状态信息(如颜色、光照、纹理等)。
视口:屏幕中显示 OpenGL 绘制内容的矩形区域,通常定义为窗口的一部分或整个窗口。
OpenGL 坐标系统
OpenGL 使用世界坐标系和窗口坐标系:
世界坐标系原点在左下角,y 轴向上,通常不以像素为单位。
窗口坐标系原点在左上角,y 轴向下,使用像素作为单位。
OpenGL 常用函数
OpenGL 提供了许多函数用于处理几何体、颜色、状态设置等。常见函数包括:
glVertex*()
:输入几何体的顶点。glColor*()
:设置颜色。glBegin()
和 glEnd()
:定义图元类型(如点、线、多边形等)。
通过本讲的学习,我们了解了 OpenGL 的基本概念、渲染管线以及如何编写简单的 OpenGL 程序。接下来的课程将深入探讨 OpenGL 的矩阵操作、变换、投影等更高级的图形编程技术。
计算机图形学 第四讲
计算机图形系统
图像的来源与生成
- 图像从何而来?
- 图像需要通过软件和硬件的共同协作生成。
- 软件: 例如Maya、RenderMan等建模和渲染软件。
- 硬件: 显卡(PC或大规模渲染集群上的显卡)。
输入设备
消费电子产品:
- 摄影摄像设备变得越来越普及,智能手机摄像头的像素快速提升。
- 例如:诺基亚N90(2005年,200万像素)与iPhone 6s Plus(2015年,前置500万像素,后置1200万像素)。
- 提出了一个问题:5美刀的手机摄像头能否拍出5000美刀的单反的效果?
几何体形状:
- 使用深度摄像头(如Kinect)或三维扫描仪进行形状建模。
- 例如,4步构建简易三维扫描系统:https://www.instructables.com/id/3-D-Laser-Scanner/
输出设备
阴极射线管(CRT):
- 通过电子枪发射电子束,经过聚焦和偏转系统,形成图像。
- 包括向量显示器(如1979年的Asteroids游戏)和光栅显示器。
平板显示器:
- 液晶显示器(LCD)、等离子显示器(Plasma)、发光二极管(LED)等。
- 优点包括低能耗、低辐射、无闪烁和无几何失真。
图像的基本概念
采样:
- 图像是二维域中的有规律采样,每个采样点代表颜色(如RGB)。
RGB和Alpha通道:
- 图像通常由三个通道(R、G、B)组成。
- Alpha通道用于表示透明度,取值范围为[0, 1]。
图像建模
像素与图像
像素: 是采样点加上值(而非方块)。
- 在不同显示设备上,像素的形状可能会有所不同,例如在CRT显示器上接近圆形,而在LCD屏幕上接近长方形。
离散图像与连续图像:
- 离散图像:常见的图像存储形式,定义域为离散。
- 连续图像:真实世界中的表现形式,定义域为连续。
矢量图与光栅图
矢量图:
- 由绘制命令驱动,如
move(x, y)
,可缩放矢量图形。
- 由绘制命令驱动,如
光栅图:
- 基于像素,由于离散采样可能产生锯齿效果。
图像理解
- 图像是数据点的集合:
- 可视为RGB空间中的点集合,计算灰度图像是降维问题。
- 图像是矩阵:
- 可以使用矩阵分解、低秩矩阵等方法进行处理。
- 图像是函数:
- 可使用网格对其近似,比如四边形域函数、三角形域函数。
- 图像是图:
- 使用图算法(如最大流最小割)进行分割。
基于采样的图形 vs 基于几何的图形
基于采样的图形
- 优点:
- 易于操作,图像定义在规则网格上,可以修改每个格点的颜色或位置。
- 缺点:
- 缺乏额外信息(如深度、空间位置),无法更换观察视角,只能对像素进行操作。
基于几何的图形
几何对象:
- 创建几何对象及其附属外观属性,通过计算机图形学或可视化方法渲染。
- 2D工具:Adobe Illustrator、CorelDRAW。
- 3D工具:Autodesk AutoCAD、POV-Ray。
几何图元:
- 简单几何体(球体、椎体、圆柱体等)和复杂图元(Spline、NURBS、隐函数、显函数、参数函数)。
融合方法
- 基于采样与基于几何的融合:
- 用于提高渲染速度和图像质量,例如在图像上绘制几何体,或在3D场景中使用纹理贴图。
物理成像系统
成像原理
基本元素:
- 物体、观察者、光源及其属性(如光源与物体材质的属性)。
模拟相机模型:
- 物体、观察者、光源相互独立,2D图形可视为3D图形的特例。
- OpenGL、Direct3D等API基于此模型。
光源类型
点光源:
- 如灯泡,光线从一点向四面八方发射。
方向光源:
- 如太阳,假设所有光束平行。
区域光源:
- 如吸顶灯,表面上的每个点沿所有方向发光。
图形渲染管线
渲染定义
- 渲染: 将一组对象转换为像素阵列的过程。
- 渲染管线:将3D场景转换为2D图像的一系列步骤。
渲染管线步骤
- Application(应用阶段): CPU完成碰撞检测、物理模拟、全局加速算法、动画等任务。
- Geometry(几何阶段): GPU完成几何变换,确定需要绘制的内容及位置。
- Rasterizer(光栅化阶段): GPU将屏幕空间中的二维顶点转换为像素,考虑深度和着色属性。
渲染过程
纹理映射:
- 将图像贴在几何体上,fragment的颜色由图像中相应位置的颜色决定。
深度测试:
- 通过深度测试去除被遮挡的几何体部分。
Blending(颜色混合):
- 按顺序渲染fragment,并将其线性合成。
Frame-buffer
- 双缓存:
- 使用两个独立缓存,避免闪烁。
渲染与建模
- 建模:
- 创建模型,设置材质,将模型置于场景中,设置光源和摄像机。
- 渲染:
- 使用虚拟相机“拍照”,对顶点进行处理,生成fragment,并决定最终像素颜色。
小结
渲染管线基本步骤
- 顶点处理: 对每个顶点进行独立变换。
- 光栅化: 将几何体转化为fragment。
- Fragment处理: 计算每个fragment的属性(如颜色)。
- 合并: 将fragment合并为最终的像素。
计算机图形学 第五讲
基本几何概念
几何定义与研究对象
几何研究的是n维空间中物体的表达。在计算机图形学中,关注的是二维和三维空间中的几何形态。
- 目标:通过最小的几何形状集合来表达复杂的物体。
- 三种基本几何元素:
- 点(Point):代表空间中的位置。
- 标量(Scalar):表示大小,但无方向。
- 向量(Vector):既有大小,也有方向。
笛卡尔坐标系:点在空间中的位置用笛卡尔坐标表示,例如 (x, y, z)。通过代数运算可以操作这些点,但它并非物理空间的精确模拟。
标量与向量
标量(Scalar):
- 标量只有大小,没有方向。常见的标量运算如加法和乘法是闭合的,满足交换律、结合律,并具有逆运算。
- 标量本身没有几何意义。
向量(Vector):
- 向量同时具有大小和方向。可以表示力、速度等物理量。
- 向量通常在几何中表示为带有箭头的线段,箭头方向表示向量的方向,线段的长度表示向量的大小。
- 向量的运算可以通过加法、点积、叉积等方式进行。
向量的运算
向量加法:
- 规则:向量的加法可以通过平行四边形法则实现。
- 性质:向量加法满足交换律和结合律,每个向量都有逆元素。
向量点积(内积):
- 定义:点积是两个向量分量相乘之和。
- 用途:点积可以用于计算两个向量之间的夹角,也可以用于计算向量在另一个向量上的投影。
- 公式:
$$
\mathbf{a} \cdot \mathbf{b} = |\mathbf{a}| |\mathbf{b}| \cos(\theta)
$$
其中,θ 是两个向量之间的夹角。
向量叉积(外积):
- 定义:叉积是仅在三维空间中定义的运算,其结果是一个垂直于原向量的向量。
- 方向:叉积的方向由右手定则给出。
- 公式:
$$
\mathbf{a} \times \mathbf{b} = |\mathbf{a}| |\mathbf{b}| \sin(\theta) \mathbf{n}
$$
其中,θ 是两个向量之间的夹角,n 是垂直于 a 和 b 的单位向量。
线性空间
- 定义:线性空间,也称为向量空间,是由向量和标量组成的一个空间。在线性空间中,向量的加法和标量乘法满足特定的规则。
- 矩阵的列向量空间:
- 矩阵的列向量可以形成一个线性空间,矩阵乘法可以被看作是对向量的线性变换。
点与向量的区别
- 向量无位置依赖:所有长度相等、方向一致的向量都是相等的,向量的存在与位置无关。
- 点表示位置:点表示空间中的一个具体位置,通常需要通过向量从原点进行偏移来表示点的位置。
仿射空间
- 定义:仿射空间是一个包含标量、点和向量的空间,在该空间中可以进行向量和点的加法运算。
- 坐标系的使用:仿射空间中的变换可以通过线性变换实现,将向量从一个坐标系变换到另一个坐标系。
线性组合与参数化表示
- 线性组合:向量的线性组合是给定多个向量和标量的乘积的和。通过线性组合可以表示直线、曲线、平面等几何对象。
- 参数化表示:
- 直线:可以通过线性组合的方式表示为
$$
\mathbf{P}(t) = \mathbf{P}_0 + t(\mathbf{P}_1 - \mathbf{P}_0)
$$ - 曲线:由一个参数决定,通常是非线性函数。
- 曲面:由两个参数决定,通常也是非线性函数。
- 直线:可以通过线性组合的方式表示为
表现形式
标架(Frame)
- 定义:标架是一个包含原点和基向量的坐标系。在几何学中,我们常通过标架来描述几何对象的位置和方向。
- 基向量:n 维向量空间可以通过 n 个线性无关的基向量进行表示,任何向量都可以表示为基向量的线性组合。
齐次坐标
- 定义:齐次坐标是一种表示点和向量的方法,统一了点和向量的表示形式。通过引入额外的一个维度,齐次坐标可以处理许多几何变换。
- 点与向量的区别:在齐次坐标中,当 w = 0 时,表示向量;当 w ≠ 0 时,表示点。
- 应用:齐次坐标在计算机图形学中非常重要,所有的标准几何变换(如旋转、平移、缩放)都可以通过 4x4 矩阵进行齐次坐标的操作。
坐标系变换
- 坐标变换:坐标系变换是通过基向量的线性组合实现的。当一个向量在一个坐标系中表示时,可以通过矩阵运算将其转换到另一个坐标系中。
- 4x4 矩阵:在齐次坐标中,坐标系变换可以通过 4x4 的矩阵乘法来实现。这种矩阵形式统一了点和向量的表示,同时保证了计算效率。
齐次坐标的优势
- 统一的变换方式:齐次坐标能够统一点和向量的变换,使得硬件可以高效地进行三维几何的变换操作。
- 矩阵叠加:多个变换可以通过矩阵乘法直接叠加,这使得复杂的变换可以通过简单的矩阵运算实现。
变换
广义变换
- 定义:广义变换是从一个点或向量映射到另一个点或向量的过程。通过对点集进行变换,可以实现物体的变换。
- 常见变换:包括平移、旋转、缩放、错切等变换。
仿射变换
- 定义:仿射变换是保持直线共线性的变换。它包括了物理世界中的许多重要变换,如平移、旋转、缩放、错切等。
- 共线性:在仿射变换中,直线的端点进行变换后,其他点可以通过重新连接端点得到。
平移变换
定义:平移变换是将点从一个位置移动到另一个位置的过程。
公式:
$$
\mathbf{P’} = \mathbf{P} + \mathbf{d}
$$
其中,d 是平移向量,表示平移的方向和距离。齐次坐标表示:
$$ T = \begin{pmatrix} 1 & 0 & 0 & d_x \\ 0 & 1 & 0 & d_y \\ 0 & 0 & 1 & d_z \\ 0 & 0 & 0 & 1 \end{pmatrix} $$可以通过 4x4 齐次坐标矩阵表示平移变换。
旋转变换
二维旋转:
- 定义:二维旋转是以原点为旋转中心,将向量逆时针旋转一定的角度。该变换是线性的。
- 公式: $$ \mathbf{P}' = \begin{pmatrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{pmatrix} \mathbf{P} $$其中,θ 是旋转角度。
三维旋转:
- 绕任意轴旋转:三维旋转可以围绕任意轴进行,实现三维旋转的方式有多种,包括使用四元数和旋转矩阵。
四元数旋转:
- 优势:四元数是一种表示旋转的最佳方式之一,具有稳定的插值效果。四元数的冗余信息少,计算效率高。
- 定义:四元数 q 可以表示为
$$
q = w + xi + yj + zk
$$
其中,w, x, y, z 是实数,i, j, k 是单位四元数。
非刚体变换
缩放变换:
- 定义:缩放变换是改变物体大小的变换,可以分别对 x, y, z 轴进行不同的缩放。
- 公式: $$ S = \begin{pmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} $$其中,s_x, s_y, s_z 是三个方向上的缩放系数。
错切变换:
- 定义:错切变换是一种将物体形变为平行四边形的变换。它可以沿一个轴方向对物体进行拉伸或压缩。
- 公式: $$ H = \begin{pmatrix} 1 & k_x & 0 & 0 \\ 0 & 1 & k_y & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} $$其中,k_x 和 k_y 是错切系数。
矩阵表示
矩阵运算:
- 所有点和向量都可以表示为 4D 列向量,变换可以通过 4x4 矩阵进行。
- 矩阵乘法:多个变换可以通过矩阵乘法进行叠加,变换的逆运算也可以通过矩阵求逆来实现。
矩阵乘法的非交换性:
- 矩阵乘法不满足交换律,因此不同顺序的变换会得到不同的结果。
OpenGL 中的变换
OpenGL 中的变换概述
- 状态机:OpenGL 是一个状态机,变换矩阵是状态的一部分。在绘制顶点前必须设置好变换矩阵来达到预期的效果。
- 建模:在建模过程中,物体通常是在物体坐标空间中定义的,需要通过变换将物体从其坐标空间移动到场景中。
- 矩阵堆栈:OpenGL 提供了多个堆栈来保存不同类型的变换矩阵(如 Modelview、Projection、Texture)。
CTM(当前变换矩阵)
- CTM:当前变换矩阵是一个 4x4 的齐次坐标矩阵,它可以通过一系列函数进行更改,并作用于渲染管线中后续定义的顶点上。
修改 CTM
设置 CTM 模式:
glMatrixMode(mode);
mode 取值为 GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE。
载入 CTM:
glLoadIdentity(void);
glLoadMatrix{fd}(*m);m 是指针,指向长度为 16 的数组(column major)。
乘 CTM:
glMultMatrix{fd}(*m);
变换示例:沿任意轴旋转
- 旋转示例:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(4.0f, 3.0f, 2.0f);
glRotatef(45.0f, 1.0f, 3.0f, 5.0f);
glTranslatef(-4.0f, -3.0f, -2.0f);
glBegin(...);
glVertex(...);
glEnd(...);
矩阵堆栈
- 矩阵堆栈操作:
glPushMatrix()
:将当前矩阵保存到堆栈顶。glPopMatrix()
:将堆栈顶的矩阵恢复为当前矩阵。
矩阵应用示例:绘制场景
- 绘制单个物体:定义一个绘制单元立方体的函数 drawUnitBox(),使用 OpenGL 的 GL_TRIANGLE_STRIP 进行绘制。
- 绘制桌子:通过缩放和平移操作绘制桌子的桌面和桌脚。
- 绘制多个物体:通过 glPushMatrix() 和 glPopMatrix() 实现矩阵的保存和恢复,从而绘制多个物体。
小结
基本概念
- 基本元素:点、标量、向量。
- 线性空间与仿射空间:通过线性组合与齐次坐标实现。
变换
- 常见变换:平移、旋转、缩放、错切。
- 注意:多个变换合成时的顺序会影响最终的结果。
OpenGL 实现
- 变换函数:OpenGL 提供了多种函数来操作当前变换矩阵(CTM),如 glTranslate(), glScale(), glRotate() 等。
拓展内容说明:
- 向量的运算:在向量的加法、点积和叉积部分,添加了公式和解释,帮助理解这些运算的几何意义。
- 齐次坐标的优点:补充了齐次坐标在图形学中的优势,解释了为什么齐次坐标能够高效地表示三维变换。
- 非刚体变换:对缩放和错切变换进行了详细的公式推导,帮助读者理解这些变换的矩阵形式。
- OpenGL 的矩阵操作:补充了如何在 OpenGL 中实现变换的具体代码示例,并解释了矩阵堆栈的作用和使用场景。
计算机图形学 第六讲
二维观察
二维观察概述
- 二维观察(2D Viewing):主要指在有限的屏幕上绘制二维平面图形。
- 问题:现实世界的二维平面可能是无限的,而屏幕有固定的大小,因此需要截取二维世界中的某个部分进行显示。
- 视窗(Window):二维世界中的一个矩形区域,定义了要显示的内容。
- 视口(Viewport):屏幕上显示内容的区域,由像素组成。
视窗与视口
- 视窗(Window):在二维世界中的一个连续的矩形区域,通常用一对坐标 (xmin, ymin) 和 (xmax, ymax) 来定义。
- 视口(Viewport):屏幕上由离散像素组成的矩阵。通过视窗的映射,内容会被绘制在视口内。
二维观察变换
- 二维观察变换:将二维世界中的视窗映射到屏幕中的视口。这个过程涉及平移和缩放。
- 注意:屏幕空间的原点在左上角,y 轴向下。
- 保持纵横比:为了避免图像变形,x 和 y 方向的缩放因子需要一致。即使视窗和视口的纵横比不一致,也要通过调整缩放因子来适配。
OpenGL命令
gluOrtho2D:用于创建投影矩阵,将二维相机空间中的坐标变换为屏幕空间中的坐标。
gluOrtho2D(left, right, bottom, top);
glViewport:定义最终绘制图像的视口,指定左下角位置 (x, y) 和视口的宽度与高度。
glViewport(x, y, width, height);
三维观察
三维观察概述
- 三维观察(3D Viewing):将三维世界投影到二维屏幕上。
- 区别于二维观察:三维观察的复杂性在于需要更多参数来控制观察角度和投影方式。
- 降维:三维观察实际上是将三维空间的内容通过投影变换降维到二维平面上,类似于通过相机拍摄物体。
建模与观察
- 建模变换:用于改变物体在世界坐标中的位置。
- 观察变换:用于改变从世界坐标到屏幕的投影过程,它不会改变世界中的物体本身。
三维投影类型
平行投影:投影线为平行线,投影方向称为 DOP(Direction of Projection)。
- 平面投影:保持了线性,直线仍然是直线,尽管平行线未必仍然平行。
透视投影:投影线汇聚于一点,称为 COP(Center of Projection)。这种投影方式模拟了“近大远小”的视觉效果。
经典观察
多角度正交投影:投影平面平行于对象的某个主面,投影线垂直于投影平面。常见于 CAD 和建筑设计中。
- 优点:保持距离和角度不变,适用于精确测量。
- 缺点:难以直观地观察物体的整体形状,通常需要添加等角投影图来帮助理解。
轴测投影:投影线仍然垂直于投影平面,但投影平面相对于对象的方向可以任意。会产生投影缩短现象,线段长度在图像空间中比对象空间中短。
斜平行投影:一种最为一般的平行投影方式,投影线与投影平面成任意角度。常用于建筑物的图像生成。
透视投影:投影线汇聚于一点,物体近大远小,并存在灭点(Vanishing Point)。透视投影不能保持平行,因此不能用于精确测量。
计算机观察
计算机观察概述
- 虚拟照相机模型:计算机观察基于虚拟照相机模型,理论上可以生成任何一种经典投影图。
- 区别于经典观察:计算机图形学强调对象定义和相机参数设置的独立性。
三个主要步骤
定位照相机:独立于对象的定义,设置相机的位置和方向。
- 通过修改 Modelview 矩阵实现。
设置透镜:选择平行投影或透视投影。
- 通过修改 Projection 矩阵实现。
设置裁剪体:定义视见体的范围,确定哪些内容将被投影到屏幕上。
OpenGL中的虚拟照相机
初始状态:OpenGL 中的默认相机位于原点,朝向 z 轴负方向。默认的 frustum 是以原点为中心,宽度为 2 的立方体。
Modelview 变换:负责描述物体和相机之间的相对运动。OpenGL 将建模和观察变换合并为一个 Modelview 变换,以提高计算效率。
定位照相机
照相机的三要素
- 观察参考点(VRP, View Reference Point):相机的观察参考位置。
- 观察方向(View Direction):相机的观察方向。
- 正方向(Up Direction):定义了视窗在观察参考平面上的角度。
观察坐标系
- 初始状态:观察坐标系与世界坐标系重合。
- 观察坐标系变换:通过 View Orientation Matrix 将世界坐标系变换为观察坐标系。
OpenGL中的定位照相机
gluLookAt:用于设置相机位置和方向。
gluLookAt(
eyex, eyey, eyez, // 相机位置
atx, aty, atz, // 观察点
upx, upy, upz // 上方向向量
);模型变换与观察变换:在 OpenGL 中,模型变换和观察变换被合并为一个 Modelview 矩阵。观察变换最先调用,应用于场景中的所有物体。
平行投影
正投影
- 正投影:场景中的所有物体沿垂直方向投影到观察参考平面上。
- 正投影矩阵:
glOrtho(left, right, bottom, top, near, far);
斜平行投影
- 斜平行投影:投影线与投影平面成任意角度。可以视为正投影与错切变换的组合:
- 错切变换矩阵: $$ M = \begin{bmatrix} 1 & 0 & \cot(\alpha) & 0 \\ 0 & 1 & \cot(\beta) & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$
- 错切变换矩阵:
透视投影
透视投影概述
- 透视投影:投影线汇聚于一点,模拟真实世界中的视觉效果。
- 特点:近大远小,存在灭点。透视投影是保直线的,但不是仿射变换。
齐次坐标中的透视投影
透视投影矩阵:
$$ P = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & \frac{1}{d} \\ 0 & 0 & 1 & 0 \end{bmatrix} $$其中,d 是投影距离。透视除法:透视投影的非线性缩短效果通过透视除法实现,离投影中心越远,缩短越大。
OpenGL中的透视投影
glFrustum:定义视锥体,用于透视投影。
glFrustum(left, right, bottom, top, near, far);
gluPerspective:简化透视投影的定义。
gluPerspective(fovy, aspect, near, far);
小结
- 二维观察:通过视窗和视口的映射,将二维世界的内容映射到屏幕上。
- 三维观察:通过投影将三维世界内容映射到二维屏幕上,常用两种投影方式:平行投影和透视投影。
- 计算机观察:通过虚拟相机模型实现三维场景的投影,涉及设置相机位置、投影方式和裁剪体。
拓展内容说明:
- 向量的运算:在向量的加法、点积和叉积部分,添加了公式和解释,帮助理解这些运算的几何意义。
- 齐次坐标的优点:补充了齐次坐标在图形学中的优势,解释了为什么齐次坐标能够高效地表示三维变换。
- 非刚体变换:对缩放和错切变换进行了详细的公式推导,帮助读者理解这些变换的矩阵形式。
- OpenGL 的矩阵操作:补充了如何在 OpenGL 中实现变换的具体代码示例,并解释了矩阵堆栈的作用和使用场景。
计算机图形学 第七讲
光栅化简介
光栅化定义
- 光栅化是将几何图元(如线段、多边形等)转换为像素的过程。通过光栅化,图形被离散化为屏幕上的像素。
- 与之对应的是光线追踪,它通过模拟光线传播来生成图像。
- Raster graphics 操作像素,而 Vector graphics 操作几何元素,但最终都需转换成像素。
计算机图形绘制过程
- 投影:将几何图元的顶点从三维空间映射到二维平面。
- 光栅化:将几何图元从连续的几何对象转换为离散的像素。
- 决定哪些像素与图元相关。
- 确定每个像素的颜色。
- 通过一系列高效的扫描转换算法在硬件上实现。
线段光栅化
绘制目标
- 使用像素绘制两点
(x1, y1)
与(x2, y2)
之间的线段。- 选中像素应尽可能靠近理想线段。
- 绘制出的线段应看起来尽量“直”。
- 起点应包括在像素序列中。
- 绘制应尽可能快速。
思路一:使用解析式
- 直线可以表示为方程
y = mx + c
,其中 m 为斜率,c 为截距。 - DDA 算法(Digital Differential Analyzer)通过递增 x 来计算 y 的变化。
示例代码:
void line_DDA(int x1, int y1, int x2, int y2) { |
思路二:Bresenham 算法
- Bresenham’s Algorithm 提供了一种更高效的线段绘制方法。
- 它仅使用整数运算,避免了 DDA 中的浮点运算。
- 通过比较像素与直线的相对位置,判断下一步需要绘制的像素是
(xi + 1, yi)
还是(xi + 1, yi + 1)
。
Bresenham 算法 伪代码如下:
void line_Bresenham(int x1, int y1, int x2, int y2) { |
标准代码示例:
|
解释
- 参数:
- x1, y1: 线段起点坐标。
- x2, y2: 线段终点坐标。
- 参数:
变量:
- dx: 线段在 x 方向上的变化量。
- dy: 线段在 y 方向上的变化量。
- p: 决策变量,用于判断下一个像素的 y 坐标。
- y: 当前绘制的 y 坐标。
算法过程:
- 计算 dx 和 dy。
- 初始化决策变量 p。
- 在 x 方向上循环,从 x1 到 x2:
- 绘制当前像素。
- 根据 p 的值决定 y 是否增加,更新 p 的值。
应用
- Bresenham 算法被广泛应用于图形学中,用于高效地绘制直线。由于其只使用整数运算,因此在性能和精度上都优于浮点运算的方法。
多边形光栅化
多边形光栅化概述
- 多边形光栅化决定哪些像素与多边形相关。常见的两种方法为:
- 扫描转换(Scan-conversion):沿扫描线逐行扫描,设置边界内的像素。
- 填充(Fill):从多边形内部的某个像素开始向外扩展。
判断点是否在多边形内
- Even-odd 测试:如果从多边形外任意一点引出一条直线与多边形的边相交次数为奇数,则点在多边形内。
- Winding number 测试:计算多边形围绕该点的转角度数,如果转角度不为零,该点在多边形内。
三角形光栅化
- 任意多边形可拆分为多个三角形。三角形光栅化是多边形光栅化的基础。
- 插值计算颜色:常使用基于重心坐标(Barycentric Coordinate)的插值方法。
公式如下:
$$
p = (1 - a - b) * p1 + a * p2 + b * p3;
$$
- Edge-equation 方法:通过判断点是否位于三角形的三条边的同一侧来确定点是否在三角形内。
抗锯齿
锯齿现象
- 锯齿现象(Aliasing)是由于对几何物体的离散化导致的。它包括:
- 边缘的锯齿状效果。
- 渲染细节丢失。
- 微小物体的丢失。
抗锯齿方法
超级采样抗锯齿(Super-sampling anti-aliasing, SSAA):
- 在比目标分辨率更高的分辨率下进行采样,然后将多个像素合并为一个像素。
比率方法(Ratio method):
- 根据像素到线段的距离来决定颜色比例。
区域采样(Area sampling):
- 扫描几何图元覆盖的像素区域,并根据像素距离边界的远近调整颜色。
显卡上的常见抗锯齿设置
多重采样抗锯齿(MSAA):
- 只对多边形的边缘进行抗锯齿处理,比 SSAA 更高效。
快速近似抗锯齿(FXAA):
- 一种基于后期处理的抗锯齿方法,完全使用图像处理方式进行模糊。
小结
- 光栅化是计算机图形学中将几何图元转化为像素的过程。
- Bresenham 算法通过整数运算提供了高效的线段绘制方法。
- 多边形光栅化可通过扫描转换或填充方法来实现,三角形光栅化是其基础。
- 抗锯齿用于解决离散化过程中出现的锯齿问题,常用的方法包括超级采样和区域采样。