1 What is OpenGL?
- 软件接口定义:OpenGL是连接软件与图形硬件的接口,为创建交互式三维应用程序提供了丰富的命令集。
- 命令数量与构成:包含超过700条不同命令,其中约670条在OpenGL 3.0版本中定义,另外50条属于OpenGL Utility Library,这些命令用于指定绘制所需的对象和操作。
- 应用场景描述:通过使用这些命令,开发者能够构建具有交互性的三维应用程序,实现复杂的图形渲染和操作。
OpenGL 是硬件无关的接口,能够在多种不同的硬件平台上实现,不包含窗口任务和高级建模命令,需从几何图元构建模型,其中GLU 库提供部分建模功能。
GLU 库
OpenGL Utility Library,提供部分建模功能,如二次曲面和 NURBS 曲线与曲面,是每个 OpenGL 实现的标准部分。
比如它能够处理二次曲面(quadric surfaces),像常见的球体、圆柱体、圆锥体等都属于二次曲面的范畴,通过 GLU 提供的相关函数,开发者可以方便地创建这些规则的几何形状,并且可以对其进行诸如精细度调整、表面属性设置等操作。
此外,GLU 还支持非均匀有理 B 样条(NURBS,Non-Uniform Rational B-Splines)曲线和曲面的创建与处理。NURBS 在计算机辅助设计(CAD)、计算机动画等领域应用广泛,它能够精确地描述复杂的曲线和曲面形状,像汽车外形设计、高精度的工业零件曲面造型等都经常会用到 NURBS。
GLU 与 OpenGL 实现的关系
标准组成部分:GLU 是每一个 OpenGL 实现的标准组成部分,这意味着只要安装了支持 OpenGL 的图形驱动或者相关的开发环境,通常都会包含 GLU。它与 OpenGL 紧密配合,开发者在使用 OpenGL 进行图形开发时,可以很自然地调用 GLU 中的功能,无需额外复杂的配置或者单独去寻找适配的库。例如,在 Windows 系统下,安装了支持 OpenGL 的显卡驱动后,当使用 OpenGL 相关的开发工具(如 Visual C++ 结合 OpenGL 开发)时,就能直接使用 GLU 的函数来辅助进行建模等操作,就像一套完整的工具套装,OpenGL 是基础工具,而 GLU 是其中用于拓展功能的重要配件。
与窗口系统协作(GLFW)
开发者必须通过控制特定硬件的任何窗口系统来进行工作。这意味着在开发一个 OpenGL 应用程序时,需要将 OpenGL 的图形渲染功能与窗口系统的功能相结合。通常,这涉及到在窗口系统创建的窗口环境中初始化 OpenGL 上下文,然后在这个上下文中进行图形渲染。
例如,在使用 GLFW(一个跨平台的窗口和输入库)和 OpenGL 开发应用程序时,首先要使用 GLFW 创建一个窗口,然后在这个窗口的上下文中初始化 OpenGL,之后才能使用 OpenGL 命令进行图形渲染。同时,GLFW 可以处理用户输入事件,如当用户按下键盘上的某个键时,GLFW 可以捕获这个事件并通知应用程序,应用程序可以根据这个事件来改变 OpenGL 渲染的内容,如旋转图形、切换场景等。
OpenGL 图形系统能实现的各种效果
OpenGL 图形系统可通过不同技术实现线框模型、深度暗示、抗锯齿、着色、阴影、纹理、运动模糊、不同视角、雾效果和景深效果等多种逼真的图形效果
Plate 1:展示线框模型场景,可看到被遮挡部分,如由多边形构成的桌面和复杂物体地球仪的构造方式。
Plate 2:深度暗示的线框场景,远处线条更暗,使用 OpenGL 的大气效果(雾)实现深度暗示。
Plate 3:抗锯齿的线框场景,减少用像素近似平滑边缘产生的锯齿。
Plate 4:平坦着色、未受光照的场景,物体为实心但看起来“扁平”,无光源效果。
Plate 5:受光照、平滑着色的场景,物体响应光源更真实立体。
Plate 6:添加阴影和纹理,阴影需自行创建,纹理映射可将二维图像应用于三维物体。
Plate 7:场景中有运动模糊的物体。
Plate 8:从不同视角展示书封面的场景,说明图像是三维物体模型的快照。
Plate 9:再次使用雾效果,模拟空气中的烟雾颗粒,效果更显著。
Plate 10:展示景深效果,模拟相机镜头无法使所有物体聚焦,相机聚焦特定点,其他物体模糊。
术语解释
- 线框模型:所有物体以线条表示,每条线对应一个基本图形(通常是多边形)的边。
- 深度暗示:通过使远处的线条更暗来给出深度的视觉提示,OpenGL 使用大气效果(雾)实现。
- 抗锯齿:减少用像素近似平滑边缘产生的锯齿的技术。
- 平坦着色:每个多边形只用一种颜色渲染,物体看起来“扁平”。
- 受光照、平滑着色:物体响应光源,看起来更真实立体。
- 阴影:不是 OpenGL 明确定义的功能,需自行创建。
- 纹理映射:将二维图像应用于三维物体。
- 运动模糊:物体运动时产生的模糊效果。
- 视角:从不同角度观察场景。
- 雾效果:模拟大气效果,可增加深度感和真实感。
- 景深效果:模拟相机镜头无法使所有物体聚焦,相机聚焦特定点,其他物体模糊。
OpenGL 图形系统的彩色板块及主要图形操作
- 用几何图元构建形状
- 在三维空间安排对象并选择视角
- 计算对象颜色
- 将对象的数学描述和颜色信息转换为屏幕像素
在某些实现(如X Window System)中,OpenGL具备跨计算机工作的能力,这在网络环境下尤为有用,其工作模式涉及客户端与服务器概念,且协议确保了跨网络运行的可行性:
1. 跨计算机工作能力:在一些特定实现里,即使创建图形的计算机与运行图形程序的计算机不同,OpenGL也能正常工作。
2. 网络环境中的工作模式:在网络计算机环境中,运行程序并发出OpenGL绘图命令的计算机称为客户端,接收命令并执行绘图的计算机称为服务器。
3. 协议的作用:从客户端到服务器传输OpenGL命令的格式(协议)始终相同,这使得OpenGL程序能够在不同类型的计算机组成的网络中运行。若程序不在网络中运行,则同一台计算机兼具客户端和服务器的角色。
A smidgen of OpenGL Code
一个实用的 OpenGL 程序的基本结构其实很简单,主要任务包括初始化特定状态以控制 OpenGL 的渲染方式,以及指定要渲染的对象。
- 功能强大导致程序复杂:OpenGL 图形系统功能丰富,可实现多种图形操作和效果,如创建复杂的三维场景、应用光照和纹理、进行坐标变换等。这些功能的多样性使得在编写程序时需要考虑众多因素,从而可能导致程序变得复杂。
- 程序基本结构简单
- 初始化状态:程序需要初始化与渲染相关的状态,如设置清除颜色(用于确定窗口清除后的背景色)、指定颜色模式(如 RGBA 或颜色索引模式)、配置深度缓冲、启用或禁用各种功能(如光照、纹理映射、混合等)。这些状态的初始化设置会影响后续图形的渲染效果。
- 指定渲染对象:明确要绘制的几何对象,包括定义对象的顶点坐标、颜色、法向量等属性,以及指定绘制的几何图元类型(如点、线、多边形等)。通过这些操作,告诉 OpenGL 要在屏幕上绘制什么内容。
渲染(rendering),是计算机根据模型创建图像的过程。这些模型或对象由几何图元(如点、线和多边形)构成,而这些几何图元是通过其顶点来指定的。
- 渲染的定义:渲染是计算机图形学中的关键过程,即利用模型生成图像的操作。模型是对现实世界或虚拟场景中物体的抽象表示,它包含了物体的形状、颜色、纹理等信息。通过渲染,这些模型被转换为可以在屏幕或其他输出设备上显示的图像,让用户能够看到最终的视觉效果。
- 模型与几何图元的关系:模型由几何图元组成,几何图元是构建模型的基本元素。点是最基本的几何图元,它只有位置信息;线由多个点连接而成,具有长度和方向;多边形则由多个顶点围成封闭区域,如三角形、四边形等常见多边形。这些几何图元通过顶点的坐标来确定其在空间中的位置和形状,从而构建出复杂的模型。
- 顶点在几何图元中的作用:顶点是定义几何图元的关键,它不仅决定了几何图元的位置,还影响其形状和方向。对于多边形来说,顶点的顺序和位置决定了多边形的形状是凸还是凹,以及其朝向等属性。在渲染过程中,计算机根据顶点的信息计算出几何图元在屏幕上的像素位置和颜色等属性,从而生成最终的图像。
#include <whateverYouNeed.h>
main() {
InitializeAWindowPlease();
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f(0.25, 0.25, 0.0);
glVertex3f(0.75, 0.25, 0.0);
glVertex3f(0.75, 0.75, 0.0);
glVertex3f(0.25, 0.75, 0.0);
glEnd();
glFlush();
UpdateTheWindowAndCheckForEvents();
}
main()
函数的第一行用于在屏幕上初始化一个窗口,其中InitializeAWindowPlease()
是一个占位符,代表特定于窗口系统的例程(通常不是 OpenGL 调用)。接下来的两行是 OpenGL 命令,用于将窗口清除为黑色:glClearColor()
设置窗口清除后的颜色,glClear()
实际执行清除操作。一旦设置了清除颜色,每次调用glClear()
时,窗口都会被清除为该颜色,并且可以通过再次调用glClearColor()
来更改清除颜色。类似地,glColor3f()
命令设置用于绘制对象的颜色,在此例中为白色,此后绘制的所有对象都使用该颜色,直到再次调用设置颜色的命令来更改它。
- 窗口初始化:
main()
函数中的InitializeAWindowPlease()
是一个自定义的函数,用于初始化窗口。它是针对特定窗口系统(如 Windows、Linux 等)的操作,不属于 OpenGL 的标准命令。不同的窗口系统可能有不同的初始化方式,这个函数作为一个占位符,表明在实际编程中需要根据具体的窗口系统来实现相应的初始化逻辑。 - 窗口清除颜色设置与操作
glClearColor()
:该函数用于设置清除颜色,它接受四个参数,分别代表红、绿、蓝和透明度(alpha)值,这些值的范围通常在 0.0 到 1.0 之间。通过设置不同的参数值,可以确定窗口清除后的颜色。例如,glClearColor(0.0, 0.0, 0.0, 0.0)
将清除颜色设置为黑色。glClear()
:实际执行清除窗口的操作,它根据之前设置的清除颜色将窗口的颜色缓冲区清除为相应颜色。当需要更新窗口内容时,通常会先调用glClear()
来清除之前的内容,然后再绘制新的图形。每次调用glClear()
时,窗口都会被更新为当前设置的清除颜色,除非再次调用glClearColor()
来更改清除颜色。
- 绘制对象颜色设置:
glColor3f()
用于设置绘制对象的颜色,它接受三个参数,分别对应红、绿、蓝颜色分量。在这个例子中,glColor3f(1.0, 1.0, 1.0)
将颜色设置为白色。此后绘制的所有对象都将使用这个颜色,直到再次调用glColor3f()
或其他类似的颜色设置函数来更改颜色。这使得在绘制多个对象时,可以通过一次颜色设置来统一它们的颜色,或者根据需要随时更改颜色以绘制不同颜色的对象。
程序中使用的下一个 OpenGL 命令glOrtho()
,用于指定 OpenGL 在绘制最终图像时所采用的坐标系,以及图像如何映射到屏幕上。接下来在glBegin()
和glEnd()
之间的调用,定义了要绘制的对象 —— 在这个例子中,是一个具有四个顶点的多边形。多边形的 “角点” 由glVertex3f()
命令定义。从参数(x, y, z 坐标)可以猜测,该多边形是位于 z = 0 平面上的矩形。
glOrtho()
命令的作用- 定义坐标系:
glOrtho()
用于设置正交投影矩阵,从而确定了 OpenGL 绘制图像时所使用的坐标系。它接受六个参数,分别定义了视景体(viewing volume)的左右、上下、远近裁剪平面的坐标。通过这些参数,可以指定一个平行投影的空间范围,在这个范围内的物体将被投影到屏幕上。 - 图像映射到屏幕:确定了坐标系后,
glOrtho()
还规定了如何将三维场景中的物体映射到二维屏幕上。它确保了在指定的坐标系下,物体的坐标能够正确地转换为屏幕上的像素位置,从而保证绘制的图像在屏幕上的显示效果符合预期。 - 正交投影是一种投影方式,在这种投影下,物体在屏幕上的显示效果不会因为距离观察者的远近而产生大小变化,就好像是通过一个平行的 “观察通道” 来观察物体一样。
- 函数原型通常为
void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal);
其中,left
,right
,bottom
,top
参数:这些参数定义了裁剪平面(clipping plane)的边界,用于确定可视区域的范围。具体来说,left
和right
指定了左右边界的坐标,bottom
和top
指定了上下边界的坐标。它们共同定义了一个矩形的可视区域,只有在这个矩形范围内的物体才会被显示出来(在未考虑nearVal
和farVal
的情况下)。例如,如果left
为 - 1.0,right
为 1.0,bottom
为 - 1.0,top
为 1.0,那么可视区域就是一个以原点为中心,边长为 2 的正方形区域;nearVal
和farVal
参数:这两个参数定义了近裁剪平面和远裁剪平面的位置,它们用于控制物体在深度方向(也就是沿着视线方向)的可见性。在正交投影中,近裁剪平面和远裁剪平面是平行的,并且物体的大小在这个范围内不会因为深度而改变。通常情况下,nearVal
的值小于farVal
,并且它们之间的区域包含了所有要显示的物体部分。如果一个物体的一部分在这个深度范围之外,那么这部分将不会被显示。例如,nearVal
可以设置为 - 10.0,farVal
可以设置为 10.0,表示只有在这个深度区间内的物体部分才会被渲染。
- 定义坐标系:
glBegin()
与glEnd()
之间的操作- 定义绘制对象:
glBegin()
和glEnd()
之间的代码块用于定义要绘制的几何对象。在这个例子中,是一个多边形。通过在这对函数之间调用相关的顶点定义命令(如glVertex3f()
)来确定多边形的顶点位置,从而构建出多
- 定义绘制对象: