[3D 图形学基础] 读书笔记(1) Part_I(Getting Started) - Introduction

开始读这本书大概有一个多月了吧,前学后忘,所有的知识点都是看我都是“仿佛你曾经明白过我们的样子喔”不做笔记真的是不行了,打算按照书的章节来写,期待我能早日从这本书毕业呢。

介绍一下这本书先:《Foundations of 3D Computer Graphics》, by Steven J. Gortler,http://www.3dgraphicsfoundations.com/,选择读这本书而不是其他许许多多叫得上名字来的图形学经典,因为它看起来非常适合入门,基础扎实,整本书的气质非常干净,印刷精良,插图优美,看着心情就会大好。

看一下封面~很清爽有木有~

 [3D 图形学基础] 读书笔记(1) Part_I(Getting Started) - Introduction_第1张图片

扫描了一下,书的原版可以去这里


以下是第一章,因为非常基础,感觉比在其他地方看到的解释都更好理解,所以基本是通篇翻译过来的,总共也就 4-5 页的样子。

Chapter_1  Introduction

[背景介绍]

计算机图形学是一个成功的技术故事。它的基本理念,表达方式,算法和硬件实现诞生于20世纪60-70年代,并在随后的20年间发展。在20世纪90年代中期,计算机图形技术已经相当成熟,但是其影响仍旧只是局限于某些"高端"程序,例如超级计算机上的科学可视化以及昂贵的飞行模拟器。现在的我们很难相信,但是在那个年代,很多计算机科学专业的学生对3D计算机图形一无所知!

近几十年来,计算机图形的商业性有了巨大发展。每一个现代PC都能够产生高质量的计算机生成图像,大部分是以视频游戏以及虚拟现实环境的形式。整个动画工业已经从其高端(例如Pixar电影)转移到了孩子们的电视机前。对于实拍电影,视觉特效领域也已经发生了翻天覆地的变化。当今的观众们也不会在看到不可思议的计算机特效时感到畏惧——这已经在预期当中了。

在本书中,我们将会介绍计算机图形技术中基础的数学与算法。我们使用编程API(applications programming interface)OpenGL来完成其中的内容。OpenGL是一个跨平台的图形编程环境,可以用于创建实时图形程序,例如视频游戏。

1.1   OpenGL

[OpenGL 与 GLSL Shader]

OpenGL 作为一种API,实现了一系列特定的操作来绘制3D计算机图形。随着底层硬件越来越便宜,越来越多的功能也被添加到了图形硬件中,并通过 OpenGL API 暴露给用户。随后,通过写一种特定目的的小程序 —— shader,用户完全控制图形计算的某个部分也变得可行了。shader 通过 API 来传递和编译,在 OpenGL 中,这些 shader 以 GLSL —— 一种类 C 风格的语言来编写。两个可编程的主要部分分别是 vertex shader (顶点着色器) 和 fragment shader (片段着色器)。这两部分之所以开放给用户,一方面是因为将这些灵活性提供给用户非常有用,另一方面是因为这部分计算可以通过 single instruction multiple data (SIMD) (单指令多数据结构)来并行完成。例如处理几何体上不同点的操作可以独立完成,而决定一个像素是否需要被显示也与其他像素完全无关。

在现代的 OpenGL 程序中,许多(并非所有)实际上的3D图形是由用户编写的 shader 而不再由 OpenGL API 自身完成。这样来看,OpenGL 更多是关于用户如何管理数据和 shader 而较少关于 3D 计算机图形。随后,我们会对 OpenGL 完成的主要步骤进行综述,也会从较高的层次描述不同的 shader 在实现 3D 计算机图形时在这些步骤中起到的特定作用。


[几何体以三角面表示]
在 OpenGL 中,几何体用一些三角面的集合来表示。一方面,三角面对 OpenGL 来说处理起来足够简单和有效率,另一方面,我们可以用三角面来近似非常复杂的 shape (形状、模型)(图1.1)。如果我们的计算机图形程序使用更抽象的几何体表示方法,在 OpenGL 绘制之前必须将它转换为三角面的集合。

[3D 图形学基础] 读书笔记(1) Part_I(Getting Started) - Introduction_第2张图片


[OpenGL 渲染的主要步骤]

简要来说,OpenGL 的计算决定了每个三角面上每个 vertex(顶点)在屏幕上的位置,找出哪些屏幕点(即像素),位于哪个三角面上,随后再进行一些计算来决定该像素应有的颜色。现在我们来更详细的讨论一遍这个流程。


[顶点属性]

每个三角面由三个顶点组成。我们将一些数值数据关联在每个顶点上,这样的数据称为 attribute(属性)。最终,我们需要决定该顶点的位置(二维几何体用2个点而三维几何体用3个点来表示)。我们可以用其他属性在顶点上关联其他类型的数据,最终用于处理该顶点的外观。例如,我们也许会关联颜色(用RGB三个数表示)属性到每个顶点上。其他属性也许会被用来描述相关的材质属性,例如,一个表面在该顶点处的光泽度。


[从CPU到GPU: 顶点缓存]

将顶点数据从 CPU 转到 GPU的开销非常高昂,因此通常要尽量减少该操作。有一种特定的 API 调用来将顶点数据传送给 OpenGL,并将数据存入 vertex buffer (顶点缓存)中。


[OpenGL Draw Call]

当顶点数据传送给 OpenGL 后,我们可以在随后的任何时间发送 draw call (绘图调用)到 OpenGL。它会让 OpenGL 读取特定顶点缓存,并将三个一组的顶点(vertex triplet)绘制为三角面。


[Uniform Variable]

一旦给出 draw call 指令,每个顶点(即顶点的所有属性)都会分别被 vertex shader 处理(图1.2)。除了属性数据, shader 还会访问 uniform variables (一致变量)。这些变量由应用程序所设置,但你只能在 OpenGL draw call 之间设置它们,而不是对每个顶点设置它们。

[3D 图形学基础] 读书笔记(1) Part_I(Getting Started) - Introduction_第3张图片


[Vertex Shader]

vertex shader 是你自己的程序,你可以在其中放任何你想要的内容。vertex shader 最常见的用途是决定一个顶点最终在屏幕上的位置。例如,一个顶点在其属性中存有自身 3D 位置的抽象数据。同时,还可能存在uniform variable,描述了一个虚拟摄影机,用于将抽象的 3D 位置映射到实际的2D屏幕。我们将在随后的2-6章以及第10章中讲到具体的这一类计算。


[从顶点到屏幕]

当vertex shader计算出了顶点在屏幕上的最终位置后,它将其赋值给保留的输出变量gl_Position。x与y坐标值用于表示绘图窗口中的位置。窗口的左下角坐标值为(-1,-1),右上角的坐标值为(1,1)。这个正方形之外的坐标值表示绘制区域之外的位置。


[Varying Variable]

vertex shader 也可以输出其他的变量供 fragment shader 随后使用在计算三角面所覆盖到的像素的颜色中。这些输出被称为 varying variables (变化变量)因为,我们随后也很快会解释,它的值在一个三角面中的不同像素间也会有变化。


[Triangle Assembler]

完成处理后,这些顶点及其 varying variable 会被 triangle assembler(三角面装配器)收集,与对应三角面上的点分为一组。


[光栅化]

OpenGL 的下一项工作是将每个三角面绘制在屏幕上(图1.3)。这一步称作光栅化(rasterization)。它用三个顶点位置来放置每一个三角面。并随后计算屏幕上的哪些像素位于该三角面之内。光栅化程序为每个像素对每个变化变量计算插值。这表示每个变化变量的值,由三个相关的三角形顶点值混合而来。混合的比例与该像素到每个顶点的距离相关。我们将会在第13章讲到混合的具体方法。因为光栅化是一个非常特定并且经过高度优化的操作,这一步是不可编程的。



[帧缓存]

最终,对于每个像素,这些插值后的数据被传递给fragment shader(图1.4)。fragment shader 是用户用 GLSL 编写的另一个交给 OpenGL 处理的程序。fragment shader 的职能是通过传递给它的varying及uniform variables中的信息来决定像素的颜色。这些由 fragment shader 最终计算出的颜色被放置在 GPU 内存中叫做帧缓存(framebuffer)的地方。帧缓存中的数据随后送去显示在其屏幕上绘制的位置。



[渲染公式]

在 3D 图形中,我们通常计算一些公式来决定像素的颜色,这些公式模拟光线从材质表面反射的行为。该计算或许会用到存储在varying variable中,表示该像素的材质和几何体属性的数据。它或许也会使用保存在uniform variable中表示场景中光源位置和颜色的数据。通过改变 fragment shader 中的程序, 我们可以模拟光线在不同类型材质上的反弹;这样可以给固定的几何体创造出表面效果的变化,见图1.5。我们在14章中会更详细的讲这一过程。

[3D 图形学基础] 读书笔记(1) Part_I(Getting Started) - Introduction_第4张图片


[纹理映射]

作为颜色计算的一部分,我们也可以指示 fragment shader 从存储的附属图像中获取颜色数据。这样的图像称为 texture(纹理)并由uniform variable来引用。同时,称作纹理坐标(texture coordinates)的varying variable告诉 fragment shader 怎样从纹理中获取适合的像素。这一过程称作纹理映射(texture mapping),可以模拟将不同部分的图像"粘合"到每个三角面上。该过程可以用来给一个由很少三角面组成的简单几何体带来很高的视觉复杂度。图1.6为例。随后在第15章会详细讲到。

[3D 图形学基础] 读书笔记(1) Part_I(Getting Started) - Introduction_第5张图片


[深度缓冲]

当颜色被存入帧缓存时,一个称作合并(merging)的步骤决定了一个从 fragment shader 中输出的"新"颜色怎样和或许已经存在于帧缓存中的"旧"颜色混合。当深度缓冲(z-buffering)被启用时,会进行一个测试,来决定一个刚刚由 fragment shader 处理过的几何体点与另一个已经存在于帧缓存中的点相比,距离观察者更近还是更远。而帧缓存只在新处理的点距离更近时被更新。深度缓冲在从三维场景中创建图像时非常有用。我们在第11章中讨论深度缓冲。此外,OpenGL 也可以根据指示用不同比例将新旧两种颜色混合在一起。这个可以用在透明物体上。这一过程称作透明混合(alpha blending)并在第16章中讨论。因为这个混合步骤涉及到读写共享的内存(帧缓存),这一步骤也是不可编程的,但可以由不同 API 调用来控制。


[OpenGL API Sample]

在附录A中,我们讨论了一个实际的代码片段,它实现了一个简单的OpenGL程序,利用纹理映射提供了一些简单的2D绘制。这里的目标并不是学习3D图形,而是去理解API本身以及OpenGL中使用到的处理步骤。在读到第6章之前的某个时间,你需要详细的阅读附录A中的内容。


本章的PDF版可以去这里拿~


你可能感兴趣的:(图形,OpenGL,三维)