全部文章

Computer Graphics

文章目录

2024-2025 计算机图形学

计算机图形学 第一讲

课程介绍与概要

课程介绍

计算机图形学是研究如何利用计算机进行图形的表示、计算、处理与显示的科学学科。核心任务包括:

课程内容大纲

课程分为三个阶段:

  1. 相关知识背景(1-3周):包括引言、历史与应用、渲染管线、OpenGL 编程基础。
  2. 计算机图形学基础(4-13周):光栅化、几何变换、视角、曲线及曲面建模等。
  3. 进阶与扩展课题(14-17周):网格处理、光影、全局光照、纹理映射、蒙特卡洛渲染、神经网络渲染等前沿技术。

课程评分标准

计算机图形学的基本任务

建模(Modeling)

建模的核心是如何在计算机中表示三维物体和场景。常见的建模方式包括:

渲染(Rendering)

渲染是将三维几何模型转换为二维图像的过程,常见的渲染目标包括:

动画(Animation)

动画是使几何模型随时间变化的过程。常见手段包括:

交互(Interaction)

交互使用户能够控制物体的内容、结构、外观,并产生实时的视觉反馈。典型应用包括:

最早的交互式图形系统为 Sketchpad,由 Ivan Sutherland 于1963年提出,奠定了现代交互式图形系统的基础。

计算机图形学的扩展

可视化(Visualization)

可视化是计算机图形学的一个分支,主要用于数据的图形化表现,帮助用户从数据中获取有用信息。常见的可视化类别包括:

设计(Design)

设计是计算机图形学的另一应用领域,涉及到工业设计、交互设计和通信设计等。常用工具包括 CAD(计算机辅助设计)和 HCI(人机交互)系统。

参考资料

推荐教材

在线资源

渲染软件

拓展阅读建议

计算机图形学 第二讲

现代计算机图形学的发展

硬件变革:显卡运算性能的爆炸性增长

随着显卡(GPU)运算性能的快速提升,计算机图形学迎来了巨大发展。显卡的发展主要依赖于以下几个因素:

GPU 的通用计算:GPGPU

GPGPU(General-Purpose computing on Graphics Processing Unit)是将 GPU 从只处理图形任务扩展到通用计算的方案。GPGPU 的优势在于:

常见的 GPGPU 应用包括:

输入输出设备的丰富化

现代计算机图形学不仅依赖于 GPU 的提升,还受益于输入输出设备的丰富化:

计算机图形学的发展史

早期发展(1950-1970年代)

计算机图形学的里程碑(1980年代至今)

新兴趋势

计算机图形学的应用

计算机图形学的应用领域非常广泛,涉及多个行业和技术领域:

电影与动画

游戏

图像与设计

训练与模拟

地理科学与医学影像

计算机辅助设计(CAD)

如何学习计算机图形学

学习动机

学习计算机图形学的必备条件

课程目标

通过本教程,你将会学习到:

计算机图形学的前沿与资源

国际会议

相关期刊

这些期刊汇集了图形学领域的最新研究成果,是学习和了解前沿技术的重要资源。

在线资源

以上资源为学习和实践计算机图形学技术提供了强有力的支持。


通过第二讲的学习,我们了解了计算机图形学的发展历程、技术变革和广泛应用,同时也为后续的课程学习奠定了理论和技术基础。

计算机图形学 第三讲

OpenGL 编程入门

OpenGL 是什么?

OpenGL,即 Open Graphics Library,是用于渲染 2D 和 3D 矢量图形的跨平台、跨语言的应用程序接口(API)。它的主要特性包括:

OpenGL 的发展过程
OpenGL 相关的其他选择

除了 OpenGL 之外,还存在其他图形渲染解决方案,如:

OpenGL 能做什么?

OpenGL 的核心功能是图形渲染,具体来说,它可以:

OpenGL Utility Toolkit(GLUT)

GLUT 是一个实用工具包,虽然不是 OpenGL 的官方组成部分,但它提供了系统级别的输入输出功能。GLUT 提供以下功能:

GLUT 安装

对于 Windows 平台,可以按照以下步骤安装 GLUT:

  1. 下载 GLUT 库(推荐使用 FreeGLUT)。
  2. 将 glut.dll 文件复制到 {Windows DLL dir}/glut32.dll。
  3. 将 glut.lib 文件复制到 {VC++ lib path}/glut32.lib。
  4. 将 glut.h 文件复制到 {VC++ include path}/GL/glut.h。
  5. 在代码中添加 #include <GL/glut>。

在实际开发中,推荐使用更现代的工具,如 Qt,并提供了相应的程序模板。

OpenGL 是如何工作的?

OpenGL 的状态机模型

OpenGL 是一个 状态机,其工作原理是通过函数调用设置内部状态变量(如当前颜色、光源位置等)。每个状态变量都有初始值,且一旦设置状态,直到显式改变之前,状态保持不变。

OpenGL 渲染管线(Pipeline)

OpenGL 的渲染过程可以用以下简易管线(pipeline)表示:

  1. Display List:存储预编译的 OpenGL 命令列表,不能修改,执行速度快。
  2. Evaluator:处理曲线和曲面的计算,将控制点描述的曲线/曲面离散化为顶点。
  3. Per-Vertex Operations:基于顶点进行的操作,如空间变换。
  4. Primitive Assembly:将顶点组装成图元(如点、线、三角形等)。
  5. Rasterization:将图元转换为片段(fragment),每个片段对应屏幕上的一个像素。
  6. Per-Fragment Operations:对每个片段进行颜色和深度计算,最终确定屏幕上每个像素的颜色。
  7. Frame Buffer:保存渲染结果,并传输到屏幕进行显示。

OpenGL 中的函数分类

OpenGL 的函数可以分为以下几类:

OpenGL 程序结构简介

OpenGL 程序的基本文件需求

为了编写一个 OpenGL 程序,通常需要以下文件:

OpenGL 程序的基本结构

OpenGL 程序通常是事件驱动编程,其基本结构如下:

1. Configure & Open Window
2. Initializing Works
3. Handle User Event
4. Render

每个 OpenGL 程序通常包含一个无限循环,等待用户输入事件(如鼠标点击、键盘按下)并执行相应的渲染操作。

OpenGL Hello World 示例

下面是一个简单的 OpenGL “Hello World” 示例,展示了如何绘制一个基本窗口并渲染内容:

#include <GL/glut.h> // 包含 GLUT 头文件

void display() {
// 清空窗口
glClear(GL_COLOR_BUFFER_BIT);

// 绘制一个白色四边形
glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0); // 设置颜色为白色
glVertex2f(-0.5, -0.5); // 顶点1
glVertex2f( 0.5, -0.5); // 顶点2
glVertex2f( 0.5, 0.5); // 顶点3
glVertex2f(-0.5, 0.5); // 顶点4
glEnd();

// 刷新显示
glFlush();
}

int main(int argc, char** argv) {
// 初始化 GLUT
glutInit(&argc, argv);

// 设置显示模式
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

// 设置窗口大小
glutInitWindowSize(400, 300);

// 设置窗口位置
glutInitWindowPosition(100, 100);

// 创建窗口
glutCreateWindow("Hello World");

// 注册显示回调函数
glutDisplayFunc(display);

// 进入 GLUT 主循环
glutMainLoop();

return 0;
}

代码讲解:
glutInit():初始化 GLUT 库。
glutInitDisplayMode():设置显示模式,GLUT_SINGLE 表示单缓冲,GLUT_RGB 表示使用 RGB 颜色模式。
glutInitWindowSize():设置窗口大小(400x300)。
glutInitWindowPosition():设置窗口在屏幕上的初始位置。
glutCreateWindow():创建一个名为 “Hello World” 的窗口。
glutDisplayFunc():注册一个显示回调函数,当窗口需要重绘时调用。
glutMainLoop():进入 GLUT 主循环,等待事件。

OpenGL 回调函数

OpenGL 使用回调函数处理用户交互事件,如鼠标点击、键盘输入等。回调函数允许我们在事件发生时调用自定义的处理函数。

回调函数工作原理:

GLUT 回调函数示例

以下是 GLUT 回调函数的示例代码,展示如何处理键盘和鼠标事件:


// 键盘回调函数
void keyboardCB(unsigned char key, int x, int y) {
if (key == 'a') {
std::cout << "a 键被按下" << std::endl;
}
}

// 鼠标回调函数
void mousebutton(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
std::cout << "左键点击,坐标: (" << x << ", " << y << ")" << std::endl;
}
}

int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(250, 250);
glutCreateWindow("GLUT 回调示例");

// 注册回调函数
glutKeyboardFunc(keyboardCB); // 键盘事件
glutMouseFunc(mousebutton); // 鼠标事件

glutMainLoop(); // 进入主循环
return 0;
}

代码讲解:
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 的矩阵操作、变换、投影等更高级的图形编程技术。

计算机图形学 第四讲

计算机图形系统

图像的来源与生成

输入设备

输出设备

图像的基本概念

图像建模

像素与图像

矢量图与光栅图

图像理解

基于采样的图形 vs 基于几何的图形

基于采样的图形

基于几何的图形

融合方法

物理成像系统

成像原理

光源类型

图形渲染管线

渲染定义

渲染管线步骤

渲染过程

Frame-buffer

渲染与建模

小结

渲染管线基本步骤

计算机图形学 第五讲

基本几何概念

几何定义与研究对象

标量与向量

向量的运算

线性空间

点与向量的区别

仿射空间

线性组合与参数化表示

表现形式

标架(Frame)

齐次坐标

坐标系变换

齐次坐标的优势

变换

广义变换

仿射变换

平移变换

旋转变换

非刚体变换

矩阵表示

OpenGL 中的变换

OpenGL 中的变换概述

CTM(当前变换矩阵)

修改 CTM

变换示例:沿任意轴旋转

矩阵堆栈

矩阵应用示例:绘制场景

小结

基本概念

变换

OpenGL 实现

拓展内容说明:

  1. 向量的运算:在向量的加法、点积和叉积部分,添加了公式和解释,帮助理解这些运算的几何意义。
  2. 齐次坐标的优点:补充了齐次坐标在图形学中的优势,解释了为什么齐次坐标能够高效地表示三维变换。
  3. 非刚体变换:对缩放和错切变换进行了详细的公式推导,帮助读者理解这些变换的矩阵形式。
  4. OpenGL 的矩阵操作:补充了如何在 OpenGL 中实现变换的具体代码示例,并解释了矩阵堆栈的作用和使用场景。

计算机图形学 第六讲

二维观察

二维观察概述

视窗与视口

二维观察变换

OpenGL命令

三维观察

三维观察概述

建模与观察

三维投影类型

经典观察

计算机观察

计算机观察概述

三个主要步骤

OpenGL中的虚拟照相机

定位照相机

照相机的三要素

观察坐标系

OpenGL中的定位照相机

平行投影

正投影

斜平行投影

透视投影

透视投影概述

齐次坐标中的透视投影

OpenGL中的透视投影

小结

拓展内容说明:

  1. 向量的运算:在向量的加法、点积和叉积部分,添加了公式和解释,帮助理解这些运算的几何意义。
  2. 齐次坐标的优点:补充了齐次坐标在图形学中的优势,解释了为什么齐次坐标能够高效地表示三维变换。
  3. 非刚体变换:对缩放和错切变换进行了详细的公式推导,帮助读者理解这些变换的矩阵形式。
  4. OpenGL 的矩阵操作:补充了如何在 OpenGL 中实现变换的具体代码示例,并解释了矩阵堆栈的作用和使用场景。

计算机图形学 第七讲

光栅化简介

光栅化定义

计算机图形绘制过程

线段光栅化

绘制目标

思路一:使用解析式

示例代码:

void line_DDA(int x1, int y1, int x2, int y2) {
int dx = x2 - x1, dy = y2 - y1, steps;
float delta_x, delta_y, x = x1, y = y1;

steps = (abs(dx) > abs(dy)) ? (abs(dx)) : (abs(dy));
delta_x = dx / (float)steps;
delta_y = dy / (float)steps;

set_pixel(round(x), round(y));

for (int i = 0; i < steps; ++i) {
x += delta_x;
y += delta_y;
set_pixel(round(x), round(y));
}
}

思路二:Bresenham 算法

Bresenham 算法 伪代码如下:

void line_Bresenham(int x1, int y1, int x2, int y2) {
int dx = x2 - x1
int dy = y2 - y1
int p = 2 * dy - dx
int y = y1

for (int x = x1; x <= x2; ++x) {
set_pixel(x, y)
if (p >= 0) {
y += 1
p += 2 * (dy - dx)
} else {
p += 2 * dy
}
}
}

标准代码示例:

#include <iostream>
#include <vector>

void set_pixel(int x, int y) {
// 在此处实现绘制像素的逻辑
std::cout << "Drawing pixel at (" << x << ", " << y << ")\n";
}

void line_Bresenham(int x1, int y1, int x2, int y2) {
int dx = x2 - x1;
int dy = y2 - y1;
int p = 2 * dy - dx;
int y = y1;

for (int x = x1; x <= x2; ++x) {
set_pixel(x, y);
if (p >= 0) {
y += 1;
p += 2 * (dy - dx);
} else {
p += 2 * dy;
}
}
}

int main() {
// 示例:绘制从 (2, 3) 到 (10, 7) 的直线
line_Bresenham(2, 3, 10, 7);
return 0;
}

多边形光栅化

多边形光栅化概述

判断点是否在多边形内

三角形光栅化

公式如下:
$$
p = (1 - a - b) * p1 + a * p2 + b * p3;
$$

抗锯齿

锯齿现象

抗锯齿方法

显卡上的常见抗锯齿设置

小结

# CG ≠ CV