OpenGL缓冲区总结
demi 在 周三, 04/03/2019 - 14:30 提交
几乎每个图形程序的重要目标之一都是在屏幕上绘制图形。屏幕是由一个矩形像素数组组成的,每个像素都可以在图像的某一个点上显示一个某种颜色的微小方块。在光栅化阶段(包括纹理和雾)之后,数据就不再是像素,而是片段。每个片段都具有与像素对应的坐标数据以及颜色值和深度值。
几乎每个图形程序的重要目标之一都是在屏幕上绘制图形。屏幕是由一个矩形像素数组组成的,每个像素都可以在图像的某一个点上显示一个某种颜色的微小方块。在光栅化阶段(包括纹理和雾)之后,数据就不再是像素,而是片段。每个片段都具有与像素对应的坐标数据以及颜色值和深度值。
帧缓存:它是屏幕所显示画面的一个直接映象,又称为位映射图(Bit Map)或光栅。帧缓存的每一存储单元对应屏幕上的一个像素,整个帧缓存对应一帧图像。帧缓冲区是指服务器(显存)中存储像素相关信息(颜色、深度)的存储空间。系统提供了帧缓冲区对象包括多个缓冲区,有颜色缓冲区、深度缓冲区、模板缓冲区等。
图形管线(graphics pipeline)向来以复杂为特点,这归结为图形任务的复杂性和挑战性。OpenGL作为图形硬件标准,是最通用的图形管线版本。2016年正式发布的Vulkan是OpenGL ES™的继任者,它为开发者提供更大的控制权以及更透明的程序设计,从总体上比OpenGL ES具有更大的潜力将性能最大化。
OpenGL绘制三维图形时涉及多种坐标系,各个坐标系都有它各自的作用。本文将介绍以下四个常见的坐标系:模型(物体)坐标系、世界坐标系、相机(人眼)坐标系和窗口坐标系。下面我们逐个讲解这些坐标系的作用。
本文主要是对红宝书(第八版)第五章中给出的透视投影矩阵和正交投影矩阵做一个简单推导。投影矩阵的目的是:原始点P(x,y,z)对应后投影点P'(x',y',z')满足x',y',z'∈[-1,1]。
透视投影
下图为透视投影的视锥体:
注:上图中忘了标注了,远裁剪平面距离原点距离为f,近裁剪平面距离原点距离为n。
设P(x0, y0, z0),我们分别求各个坐标在投影后的值。将P点投影到近平面上,首先看x方向上的投影,沿着过P点,且平行于xoz平面切一刀,有如下图:
OpenGL着色语言(OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。
学习shader之前必须知道的事情:shader(着色语言)到底发生在那个阶段?OpenGL的渲染管线有哪些阶段?这对开发人员来说很重要,也许你刚刚接触,或者你在使用已有的产品,很优秀的游戏引擎,或者渲染引擎,你觉得知道这个没有太大意义,但知道了这些,总归对你没有坏处。
下图是一个非常简化框图流水线的各个阶段,并在他们之间传播的数据。虽然极其简单,它是足够的着色器编程,提出了一些重要的概念。固定管线中存在很多阶段,并存在很多细节,这里只是粗略的介绍。
(1)顶点变换:
在这里,一个顶点的属性,如在空间的位置,以及它的颜色,法线,纹理坐标,其中包括一组。这个阶段的输入的各个顶点的属性。由固定的功能所执行的操作,主要完成一下工作:
1. 顶点位置变换
2. 计算顶点观照
3. 纹理坐标变换
(2)图元装配:
1、深度
所谓深度,就是在openGL坐标系中,像素点Z坐标距离摄像机的距离。摄像机可能放在坐标系的任何位置,那么,就不能简单的说Z数值越大或越小,就是越靠近摄像机。
2、深度缓冲区
深度缓冲区原理就是把一个距离观察平面(近裁剪面)的深度值(或距离)与窗口中的每个像素相关联。
首先,使用glClear(GL_DEPTH_BUFFER_BIT),把所有像素的深度值设置为最大值(一般是远裁剪面)。
然后,在场景中以任意次序绘制所有物体。硬件或者软件所执行的图形计算把每一个绘制表面转换为窗口上一些像素的集合,此时并不考虑是否被其他物体遮挡。
其次,OpenGL会计算这些表面和观察平面的距离。如果启用了深度缓冲区,在绘制每个像素之前,OpenGL会把它的深度值和已经存储在这个像素的深度值进行比较。新像素深度值<原先像素深度值,则新像素值会取代原先的;反之,新像素值被遮挡,他颜色值和深度将被丢弃。
混合是什么呢?混合就是把两种颜色混在一起。具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。
假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。在绘制红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混合,于是得到一种新的颜色,看上去就好像玻璃是半透明的。
要使用OpenGL的混合功能,只需要调用:glEnable(GL_BLEND);即可。
要关闭OpenGL的混合功能,只需要调用:glDisable(GL_BLEND);即可。
注意:只有在RGBA模式下,才可以使用混合功能,颜色索引模式下是无法使用混合功能的。
一、源因子和目标因子
前面我们已经提到,混合需要把原来的颜色和将要画上去的颜色找出来,经过某种方式处理后得到一种新的颜色。这里把将要画上去的颜色称为“源颜色”,把原来的颜色称为“目标颜色”。
绝大数OpenGL实现都有相似的操作顺序,一系列相关的处理阶段称为OpenGL渲染管线。图1-2显示了这些顺序,虽然并没有严格规定OpenGL必须采用这样的实现,但它提供了一个可靠的指南,可以预测OpenGL将以什么样的顺序来执行这些操作。
如果读者刚开始涉足三维图形编程,可能会对接下来的内容感到吃力。读者现在可以跳过这一部分内容,但在读完这本书的每一章时,都应该重温一下图1-2。