《视觉开发专题》之 OpenGL 概述

栏目: 后端 · 发布时间: 5年前

内容简介:这是这几个小模块来一一介绍,阅读完本篇内容你将收获:友情提示:该篇文字较多,比较适合对 OpenGL 知之甚少的同学阅读,已经有相关经验的大佬可以溜了:stuck_out_tongue_closed_eyes:,闲言少叙,直入正题。

这是 视觉专题 的第一篇,将分为:

  1. 什么是 OpenGL
  2. OpenGL 语法说明
  3. OpenGL 渲染管线
  4. OpenGL 程序&渲染流程分析

这几个小模块来一一介绍,阅读完本篇内容你将收获:

  1. OpenGL 是什么
  2. OpenGL 渲染管线的工作流程

友情提示:该篇文字较多,比较适合对 OpenGL 知之甚少的同学阅读,已经有相关经验的大佬可以溜了:stuck_out_tongue_closed_eyes:,闲言少叙,直入正题。

注: 该专题默认使用 核心模式 来进行,需要 OpenGL 的版本在3.3以上。

一:什么是 OpenGL

一般它被认为是一个 API (Application Programming Interface, 应用程序编程接口),包含了一系列可以操作图形、图像的函数(通过直接访问图形硬件设备的特性来实现)。事实上,OpenGL 本身并不是一个API,它仅仅是一个由 Khronos 组织制定并维护的规范(Specification)。

OpenGL 规范严格规定了每个函数该如何执行,以及它们的输出值。至于内部具体每个函数是如何实现(Implement)的,将由 OpenGL 库的开发者自行决定(这里开发者通常是显卡的生产商)。

因为 OpenGL 规范并没有规定实现的细节,具体的 OpenGL 库允许使用不同的实现,只要其功能和结果与规范相匹配即可。所以,当你使用 Apple 系统的时候,OpenGL 库是由 Apple 自身维护的。在 Linux 下,有显卡生产商提供的 OpenGL 库,也有一些爱好者改编的版本。这也意味着任何时候 OpenGL 库表现的行为与规范规定的不一致时,基本都是库的开发者留下的bug。

OpenGL 是使用客户端 - 服务端的形式实现的,我们编写的应用程序可以看做客户端,而计算机图形硬件厂商所提供的 OpenGL 实现可以看做服务端。我们编写的 OpenGL 命令,最终会被转换为相关的协议提交给服务端,然后被执行并产生图像内容。

二:OpenGL 语法

OpenGL 库中所有的函数都会以字符“gl”作为前缀,然后是个或多个大写字母开头的词组,以此来命名一个完成的函数(如 glBinVertexArray() )。除此之外你还会看到“glfw”开头的函数,它们来自第三方库GLFW,这是一个抽象化窗口管理和其他系统任务的开发库。类似的,还有“gl3w”开头的函数,它们来自三方库 GL3W 。后续会进一步展开讲这两个库的内容。

与函数命名约定类似,OpenGL 库中定义的常量采用“GL_”开头,通过 #define 来完成常量的定义。为了方便在不同的操作系统之间移植 OpenGL 程序,OpenGL 还为函数定义了不同的数据类型,如 GLfloat ,所以最好统一使用 OpenGL 定义的数据类型,这样就不需要关心系统兼容性问题了。

由于 OpenGL 是一个 C 语言形式的库,因此它不能使用函数的重载来处理不同类型的数据,它通过函数名称的细微变化来实现同一类功能函数集的管理。举个例子: glUniform2f()glUniform3fv() ,前者的后缀 2f 表示这个函数需要两个 GLfloat 类型的参数(以此类推,目前一共定义了24种不同的 glUniform* ()函数),后者的后缀多出的一个 v 是 vector 的缩写,即表示它需要传入一个包含三个 GLfloat 类型元素的一维数组作为参数。

所有可以作为后缀的字母,以及它们所对应的数据类型:

《视觉开发专题》之 OpenGL 概述

三:OpenGL 渲染管线

早期的(3.3版本以前) OpenGL 使用 立即渲染模式 (Immediate mode,即固定渲染管线):OpenGL的大多数功能都被库隐藏起来,开发者很少能控制 OpenGL 计算的过程。固定渲染管线较容易使用和理解,但是效率太低且不够灵活。

当使用OpenGL的核心模式时,OpenGL 迫使我们使用现代的函数,现代函数具有更高的灵活性和效率性,也能让人更容易清楚 OpenGL 是如何运作的,更好的理解图形编程。但入门门槛也稍有增加。

我们通常所说的 渲染管线 (rendering pipeline),它包含了两个部分:第一部分把你的3D坐标转换为2D坐标,第二部分是把2D坐标转变为实际的有颜色的像素。下图是 OpenGL4.5 版本的 管线 示意图:

《视觉开发专题》之 OpenGL 概述
OpenGL 首先接收用户提供的几何数据(顶点和几何图元),并且将它输入到一系列着色器阶段中进行处理,然后将处理后的数据送入光栅化单元(rasterizer)。光栅化单元负责对所有剪切区域内的图元生成片元数据,我们可以将一个片元视为一个“候选的像素”,然后对每个生成的片元都执行一个片元着色器,这一步会计算出这个片元的最终颜色。注意,即使在片元着色器中计算出来了一个像素输出的颜色,在渲染多个三角形的时候最后的像素颜色也可能完全不同,还会受 深度混合

的影响,这个后面会详细讲。

我们可以通过控制我们需要的着色器来实现自己所需的功能,事实上,只有顶点着色器和片元着色器是必需的,细分和几何是可选的步骤。为了更好理解顶点着色器和片元着色器的分工和区别,可以总结为: 顶点着色(包括细分和几何着色)决定了一个图元应该位于屏幕的什么位置,而片元着色使用这些信息来决定某个片元的颜色应该是什么

五:OpenGL 程序&渲染流程分析

无论 OpenGL 的程序写的有多么庞大与复杂,它的基本结构通常都是类似的:

  1. 初始化物体渲染所对应的状态。
  2. 设置需要渲染的物体。

在上代码之前,咱们需要对必要的图形学名词有基本的理解。

  • 渲染 :计算机从模型到最终的图像创建的过程。OpenGL 只是计算机渲染系统的其中一种,基于光栅化的系统。 Object,IBO. 决定了绘制顶点的顺序,避免顶点数据重复造成的资源浪费。
  • OpenGL 状态机 :可以看做一个上下文(context),在调用任何 OpenGL 的指令之前,都需要先创建并进入这样的上下文中,它可以记录自己当前的状态,并能接收新的输入(调用 OpenGL 函数),当关闭了上下文,就不再接收输入。
  • 着色器 (Shader) :为 图形渲染管线 中的某个特定部分,将输入转化为输出的程序。在 OpenGL 中,会涉及到六种不同的着色阶段,其中最常用的包括 顶点着色器 以及 片元着色器 ,前者用于处理顶点数据,后者用于处理光栅化后的片元数据。着色器运行在 GPU 上,在 OpenGL 使用它之前,必须经过编译并链接为一个 着色器程序对象 (Shader Program Object)。

一个简单顶点着色器的源代码长这样:

void main(){
    gl_Position = ftransform();
}
复制代码

一个简单片元着色器的源代码:

void main() {
    gl_FragColor = vec4(1.0,0.5,0.2,1.0);
}
复制代码

它们都需要用GLSL (OpenGL Shading Language,着色器语言) 。

  • 标准化设备坐标(Normalized Device Coordinates, NDC):一旦你的顶点坐标已经在顶点着色器中处理过,它们就应该是标准化设备坐标了,标准化设备坐标是一个x、y和z值在-1.0到1.0的一小段空间。任何落在范围外的坐标都会被丢弃/裁剪,不会显示在你的屏幕上。

  • 像素:显示器上最小的可见单元。

  • 帧缓存:保存着所有计算机生成的图像的像素点,它是由图形硬件设备管理的一块独立内存区域,可以直接映射到最终的显示设备上。

  • 顶点缓冲对象:Vertex Buffer Object, VBO . 管理着在GPU内存(通常被称为显存)中,一块储存着大量顶点数据的内存。因为从CPU把数据发送到显卡相对较慢,所以只要可能我们都要尝试尽量一次性发送尽可能多的数据。

  • 顶点数组对象:Vertex Array Object, VAO . 可以像顶点缓冲对象那样被绑定,任何随后的顶点属性调用都会储存在这个 VAO 中。这样的好处就是,当配置顶点属性指针时,你只需要将那些调用执行一次,之后再绘制物体的时候只需要绑定相应的 VAO 就行了。这使在不同顶点数据和属性配置之间切换变得非常简单。

    《视觉开发专题》之 OpenGL 概述
    当你打算绘制多个物体时,你首先要生成/配置所有的VAO(和必须的VBO及属性指针),然后储存它们供后面使用。当我们打算绘制物体的时候就拿出相应的VAO,绑定它,绘制完物体后,再解绑VAO。
  • 索引缓冲对象:Element Buffer Object,EBO或Index Buffer. 专门储存顶点绘制的索引,OpenGL调用这些顶点的索引来决定该绘制哪个顶点。由于三角形是绘制的基本图形,对于一些复杂图形会存在很多三角形(共用边)的顶点重合问题,该索引就是为了解决此问题,从而降低开销。

我写了一份简单的 OpenGL 示例程序 给你作参考,附有比较详细的渲染流程分析,需要的同学自取,这里就不占篇幅粘代码了。用 Xcode 打开程序直接 Run, 就可以看到该效果:

《视觉开发专题》之 OpenGL 概述

这份 Demo 使用了可编程渲染管线,自定义了简单的着色器,初学者不需要搞清楚每一步的原理,先对 OpenGL 的语法和基本结构有个初步的了解就行。

总结

枯燥的概念和晦涩的专业术语很容易让初学者望而生畏,所以此篇我只选了一些必要的概念,做了简要的介绍。建议结合文中提供的源码,把上面涉及到的步骤一一拆解,进而加深对相关概念以及 OpenGL 工作流程的理解。

近来因工作和身体原因,文章更新滞后了两周有余,现已恢复正常。

下一篇文章将使用 固定管线 来完成一些动画效果,顺带介绍涉及到的 OpenGL 知识,这样更好理解。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Data Mining

Web Data Mining

Bing Liu / Springer / 2011-6-26 / CAD 61.50

Web mining aims to discover useful information and knowledge from Web hyperlinks, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is not purely an ......一起来看看 《Web Data Mining》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码