openGL生产的3D渲染模型
一、简介
OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来绘制从简单的图形到比较复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。
OpenGL被设计为只有输出的,所以它只提供渲染功能。核心API没有窗口系统、音频、打印、键盘/鼠标或其他输入设备的概念。虽然这一开始看起来像是一种限制,但它允许进行渲染的代码完全独立于他运行的操作系统,允许跨平台开发。然而,有些集成于原生窗口系统的东西需要允许和宿主系统交互。
创建和历史:
1992年,SGI公司领导了OpenGL架构审查委员会(OpenGL ARB)的创建。该委员会由若干公司组成,负责未来OpenGL规范的维护和扩展。
1997年,SGI推出了OpenGL 1.1版本,性能比1.0版有显著提高。
新增顶点数组
纹理对象
复制像素操作
多边形偏移
2004年,OpenGL 2.0(2004年9月7日)
可编程着色器(GLSL)
浮点纹理和渲染缓冲区
非幂次纹理
多重渲染目标(MRT)
目前Flutter支持的OpenGL的库有很多,但是目前来看支持率都不是高。
功能:
作为独立于操作系统的开放的三维图形的软件开发包,在其基础上开发的应用程序能够简单方便的移植于各种平台。其具有七大功能:
建立3D模型:OpenGL除了能够处理一般的2D图形,即点、线、面的绘制外,主要任务是集合了3D立体的物体绘制函数。
图形变换:OpenGL利用基本变换以及投影变换处理图形。所谓的基本变换就是在处理2D平面图形时的平移、旋转、变比、镜像变换。投影变换就是在处理3D立体图形时的平行投影以及透视投影。通过变换方式,可以将2D的平面图形清晰明了的变换成3D的立体图形,从而在减少计算的时间的同时就能够提高了图形显示的速度。
颜色模式:OpenGL库中的颜色模型:使用较为广泛的RGBA模式以及颜色索引模式(color index)。
光照、材质的设置:OpenGL库中包含了多种光照的类型。材质是用光反射率来表示的。其原理是基于人眼的原理,场景中的物体是由光的红绿蓝的分量以及材质的红绿蓝的反射率的乘积后所形成的颜色值。
纹理映射:纹理指的是物体表面的花纹。OpenGL库中集合了对于物体纹理的映射处理方式,能够十分完整的复现物体表面的真实纹理。
图像增强功能和位图显示的扩展功能:OpenGL的功能包括像素的读写、复制外,以及一些特殊的图像处理功能:比如,融合、反走样、雾的等等特殊的处理方式。对于图像的重现和处理,可以使得效果更有真实感,逼真。
双缓存功能:OpenGL创新性的运用了双缓存形式。计算场景、生成画面图像、显示画面图像分别将其由前台缓存和后台缓存分开处理,大大提高了计算机的运算能力以及画面的显示速度。
优势:
具有强大的通用性和可移植性,可以将其轻松的移植在多个不同的平台上进行二次开发。因为OpenGL本身是一个与硬件无关的软件接口,所以,通用于市面上较为流行的平台:比如,Windows、Unix、Linux、MacOS等。
能够转换3D图形设计软件制作的模型文件。OpenGL仅仅作为一个图形的底层图形库,并没有提供直接描述某个场景地几何实体的圆元。但是,为了其转换的方便性,其内部集合了许多转换函数,可以快速方便的将3DS/3DSMAX、AutoCAD等3D绘制的图形设计制作出的DXF以及3DS模型的文件转换成数组的形式,从而将图像转换成数据进行编程处理。
配备了高级图形库:Open Inventor、Cosmo3D、Optimizer等。这些软件库针对于创建、编辑以及处理分析三维的立体场景提供了高级的应用程序单元;提高不同类型的图形格式的交换数据的能力。 [2]
二、OpenGL库介绍
官方定义——OpenGL(Open Graphics Library,译名:开放式图形库)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。
这个接口由近350个不同的函数调用组成,用来绘制从简单的图形比特到复杂的三维景象。
2.1、gl库:
是一个图形程序库,主要用于UNIX系统下的图形编程。它属于OpenGL的一部分,提供了基本图素、坐标转换、设置属性和显示方式、I/O处理以及真实图形显示等功能1。此外,gl库还指代一个基于Go语言的OpenGL绑定库,旨在让Go开发者能够轻松地利用OpenGL图形库进行高效且灵活的3D图形编程。这个库提供了一个全面的API接口,用于与OpenGL进行交互,支持创建复杂的3D模型和实现逼真的渲染效果,适用于游戏开发、数据可视化、虚拟现实和科学计算等领域
2.2、GLEW库:
全称OpenGL Extension Wrangler Library,是一个用于管理OpenGL扩展功能的库。由于OpenGL只有函数声明而没有实现,所以不同的显卡生产商会提供自己的实现。这就需要在编写程序时判断哪些函数是否可用,非常麻烦。而GLEW库则将这些问题简化,使得各个版本的OpenGL函数像原生函数一样可以直接调用。
2.3、GLFW库:
是专门针对OpenGL的C语言库,GLFW是一个专门用于处理窗口创建和事件循环的库,它能够兼容各种操作系统,提供了一个简单的API来处理窗口相关的操作,如创建、销毁、调整大小等。GLFW负责创建窗口、处理窗口相关的事件(如键盘和鼠标输入),并提供一个OpenGL上下文供程序使用。
三个库的关系:
这三个库的关系可以这样理解:首先,GLFW负责创建和管理窗口以及处理用户的输入事件;然后,OpenGL则负责渲染2D、3D图形;最后,GLEW则提供了对OpenGL更高版本函数的支持,使得开发者可以在不改变代码的情况下使用新版本的OpenGL功能。这三者相互配合,共同完成了图形应用程序的开发。
2.4、glut库
GLUT库是一个跨平台的OpenGL实用工具库,旨在简化OpenGL程序的开发。它提供了一系列功能,包括窗口管理、输入处理和基本的图形绘制,使得开发者可以更容易地创建图形用户界面(GUI)和进行基本的3D图形渲染。GLUT库不依赖于特定的窗口系统,这使得它可以在不同的操作系统和平台上使用,包括Windows、Linux和macOS等。12
GLUT库的使用通常涉及几个步骤,包括下载和安装GLUT库,然后在开发环境中配置项目以包含GLUT库。例如,在使用CLion或Visual Studio等集成开发环境(IDE)时,需要修改项目的配置文件(如CMakeLists.txt),添加对GLUT库的引用,以便在编译时链接到GLUT库。56
此外,GLUT库虽然适合用于学习和开发简单的OpenGL应用程序,但对于需要复杂用户界面的大型应用程序,建议使用更强大的本地窗口系统工具包。总的来说,GLUT库是一个有用的工具,特别是对于初学者和需要跨平台兼容性的开发者。
三、OpenGL详解
3.2 图形渲染管线的初步了解:
在 OpenGL 中,任何事物都在 3D 空间中,而屏幕和窗口却是 2D 的空间,这导致 OpenGL 的大部分工作都是关于把 3D 坐标转变为适应你屏幕的 2D 坐标。
3D 坐标转为 2D 坐标的处理过程是由 OpenGL 的图形渲染管线管理的。(Graphics Pipeline,大多译为管线,实际上指的是 一堆原始图形数据途经一个输送管道,期间经过各种变化处理,最终出现在屏幕的过程 )
它们具有并行执行的特性,它们在GPU上为每一个(渲染管线)阶段运行各自的小程序,从而在图形渲染管线中快速处理你的数据。这些小程序叫做着色器(Shader)。
图形渲染管线可以被划分为两个主要部分:第一部分把 3D 坐标转换为 2D 坐标,第二部分把 2D 坐标转变为实际有颜色的像素。
3.3 缓存(buffer)
GPU和CPU都有自己独占的内存区域,OpenGL ES为两个内存区域间的数据交换定义了缓存(buffer)的概念。缓存是指图形处理器能够控制和管理的连续的RAM。几乎所有程序提供给GPU的数据都应该放入缓存中。
3.4 帧缓存(frame buffer)
就像GPU提供数据的缓存一样,接收渲染结果的缓冲区叫做帧缓存。可以同时存在很多的帧缓存,并且可以通过OpenGL ES让GPU把渲染结果存储到任意的帧缓存中。有front frame buffer和back frame buffer的概念,front frame buffer控制屏幕上显示的像素颜色和布局,所以一般不会直接渲染到front frame buffer中,这样的话就会让用户看到没有渲染完成的图像。相反程序会把渲染结果保存到包含back frame buffer的其他frame buffer中,当back frame buffer渲染成功之后就会立即与front frame buffer进行交换。
3.5 OpenGL ES context
Context 封装了配置OpenGL ES保存在特定平台的数据结构信息。因为OpenGL ES是一个状态机,这意味着在一个程序中配置之后就会一直保留这个值,直到程序修改了这个值。上下文信息可能被保存在CPU所控制的内存中,也可能在GPU所控制的内存中。OpenGL ES Context的内部实现依赖于不同的嵌入式系统和GPU硬件,所以OpenGL ES提供了标准的ANSI C语言函数来与Context交互。OpenGL ES Context会跟踪用于渲染的帧缓存,一会跟踪用于几何数据、颜色等的缓存。
四、OpenGL应用
4.1绘制一个长方体:
4.2编写顶点位置:
接下来我们要看下坐标轴
cubewidth对应长方体的宽度,cubeHeight对应长方体的高度对应我们的关键代码:
/* 创建vertex。 */
float vertext[] = {
0.0, 0.0, 0.0, //A点
cubeWidth, 0.0, 0.0, //B点
cubeWidth, cubeWidth, 0.0, //C点
0.0, cubeWidth, 0.0, //D点
0.0, 0.0, cubeHeight, //A1点
cubeWidth, 0.0, cubeHeight,//B1点
cubeWidth, cubeWidth, cubeHeight,//C1点
0.0, cubeWidth, cubeHeight,//D1点
};
补充:
OpenGL 是一个 3D 图形库,所以我们在 OpenGL 中指定的所有坐标都是 3D 坐标(x、y和z)。仅当 3D 坐标在3个轴 (x、y和z) 上都在 -1.0 到 1.0 的范围内时才处理它。这个是 标准化设备坐标 (Normalized Device Coordinates, NDC)。
定义这样的顶点数据以后,我们会把它作为输入发送给图形渲染管线的第一个处理阶段:顶点着色器
4.3编写着色器:
顶点着色器:顶点着色器主要负责处理图形的顶点信息,包括顶点的位置、颜色、法线、纹理坐标等。它的主要任务是将模型从模型空间变换到裁剪空间,并进行光照计算、纹理坐标生成等操作。顶点着色器对每个顶点执行一次,生成变换后的顶点位置信息,这些信息随后被传递给片元着色器进行处理。
片元着色器:片元着色器则处理由顶点着色器生成的每个像素或片段的颜色和其他属性。它接收从顶点着色器传递过来的插值数据,并根据这些数据计算每个像素的颜色和其他效果,如纹理采样、颜色混合等。片元着色器对每个像素或片段执行一次,最终决定屏幕上每个像素的颜色和其他属性。
编写顶点着色器需要用到 “着色器语言GLSL(OpenGL Shading Language) ”,然后编译这个着色器,这样我们就可以在程序中使用它了,以下为一些主要使用着色器的方法:
例如以下代码:
NSString *vertexShader = @"precision highp float;\n\
attribute vec3 aVertex;\n\
attribute vec4 aColor;\n\
uniform mat4 aViewMatrix;\n\
uniform mat4 aProjectionMatrix;\n\
uniform mat4 aTransformMatrix;\n\
uniform mat4 aScaleMatrix;\n\
varying vec4 color;\n\
void main(){\n\
gl_Position = aProjectionMatrix * aViewMatrix * aScaleMatrix * vec4(aVertex, 1.0);\n\
color = aColor;\n\
}";
为了设置顶点着色器的输出,我们必须把位置数据赋值给预定义的 gl_Position变量。
1、glCreateProgram 函数会创建一个着色器程序,并返回新创建程序对象的ID。
_program = glCreateProgram();
2、创建顶点着色器对象
GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
3、 将顶点着色器的内容进行配置
glShaderSource(vShader, 1, &vByte, &vlength);
4、编译顶点着色器
glCompileShader(vShader);
5、把编译好的顶点着色器附加到程序对象上
glAttachShader(_program, vShader);
glLinkProgram(_program);
以上为OpenGL模型绘制模型和颜色的主要过程