图形编程指南
1. OpenGLES编程指南
1.1 简介
OpenGLES是一种专为 嵌入式设备 设计的轻量级3D图形库,是OpenGL标准的一个子集。它提供了跨平台的API ,适用于移动设备和资源受限的系统。OpenGLES相较于OpenGL的主要区别有:
- 数据类型 :不支持double型,新增高性能定点小数类型
- 绘图命令 :取消glBegin/glEnd/glVertex,仅保留glDrawArrays等
- 纹理处理 :要求直接提供压缩贴图,提高渲染效率
EGL(Embedded Systems Graphics Library)是OpenGL ES生态系统中的关键组件,充当 OpenGL ES渲染API和本地窗口系统之间的桥梁 。作为一个独立于平台的接口层,EGL屏蔽了不同硬件平台和操作系统之间的差异,为OpenGL ES提供了统一的操作环境。EGL的主要功能包括:
- 图形上下文管理 :创建和维护OpenGL ES渲染上下文
- 表面/缓冲区创建 :负责创建绘图表面和缓冲区
- 渲染同步 :协调OpenGL ES与显示设备进行同步,确保渲染结果正确显示
- 资源管理 :管理纹理贴图等渲染资源
1.2 渲染流程
在OpenGLES和EGL的协同工作中,渲染流程是整个图形渲染系统的核心,下图简要展示了 OpenGLES 进行图形渲染的过程。

整个图形渲染的流程具体包括以下5个步骤:
-
EGL初始化 EGL初始化是渲染流程的第一步,它为后续的渲染操作奠定基础。在这个阶段,开发者需要完成以下关键操作:
- 获取EGLDisplay对象:通过eglGetDisplay()函数获取与本地窗口系统相连的EGLDisplay对象。
- 初始化EGL环境:调用eglInitialize()函数初始化EGL环境,获取EGL的版本信息。
- 选择EGLConfig:使用eglChooseConfig()函数选择合适的EGL配置,指定所需的渲染属性,如颜色深度、alpha通道等。
- 创建EGLContext:通 过eglCreateContext()函数创建EGL渲染上下文,指定OpenGL ES的版本和所需的其他选项。
-
创建渲染表面 接下来,需要创建一个渲染表面,作为OpenGLES渲染的目标。EGL提供了几种创建渲染表面的方法:
- 窗口表面 :使用eglCreateWindowSurface()函数创建与窗口系统关联的渲染表面。
- 离屏表面 :通过eglCreatePbufferSurface()函数创建离屏渲染表面,常用于生成纹理。
- 位图表面 :利用eglCreatePixmapSurface()函数创建基于位图的渲染表面。
-
设置渲染上下文 在创建完渲染表面后,需要将EGLContext与EGLSurface关联起来,以便OpenGLES可以使用正确的渲染上下文进行渲染。这一步骤通常通过eglMakeCurrent()函数完成。
-
OpenGLES渲染操作 一旦EGL环境设置完毕,就可以开始使用OpenGLES进行渲染了。OpenGLES渲染流程通常包括以下步骤:
- 设置视口 :使用glViewport()函数定义渲染的区域。
- 清除缓冲区 :调用glClear()函数清除颜色、深度和模板缓冲区。
- 激活着色器程序 :通过glUseProgram()函数激活预先准备好的着色器程序。
- 传递渲染参数 :使用glVertexAttribPointer()等函数传递顶点坐标、纹理坐标等参数。
- 绘制图元 :调用glDrawArrays()或glDrawElements()函数绘制几何形状。
-
交换缓冲区 渲染完成后,需要将渲染结果从后缓冲区交换到前缓冲区,以便在屏幕上显示。这一步骤通常通过调用eglSwapBuffers()函数完成。此外,EGL还提供了同步机制,如eglWaitSyncKHR()函数,用于等待特定的渲染操作完成。这在处理复杂的渲染场景或多线程渲染时,可以帮助开发者更好地控制渲染流程的时间和顺序。
1.3 EGL API
EGL API通过Mesa3D提供具体实现,在 k1x-gpu-test Demo 中提供了k1平台上的调用示例和封装。前面的渲染流程中已经提及了在一次渲染过程中主要使用的几个EGL API,更详细的用法可以参考:
1.4 OpenGLES API
目前的GPU DDK支持最新的OpenGLES 3.2, 以下列举几个主要的API用法示例:
-
void glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
用于将指定的源码字符串加载到指定的着色器对象中。shader:指定要加载源代码的着色器对象。
count:指定要加载的源代码字符串的数量。
string:一个指向包含源代码字符串的数组的指针。
length:一个可选的指向 每个源代码字符串长度的数组的指针。如果提供了这个参数,那么它应该包含与 string 数组相同数量的元素,并且每个元素都指定了相应源代码字符串的长度。如果 length 为 NULL,则假定所有的源代码字符串都是以空字符 '\0' 结尾的。 -
在加载源代码后,需调用
void glCompileShader(GLuint shader)
来编译着色器。它将源码编译成可执行的机器代码,并将结果存在一个着色器对象中。shader 是要编译的着色器对象的标识符。调用 glCompileShader 函数后,可通过调用glGetShaderInfoLog
函数来获取编译过程中的错误信息。 -
glCreateProgram
用于创建一个新的 OpenGL 程序对象,并返回一个指向该对象的句柄。程序对象是一个用于存储和管理 OpenGL 程序的容器。GLuint program = glCreateProgram(); //创建一个新的 Open GL 程序对象
-
void glAttachShader(GLuint program, GLuint shader)
用于绑定着色器对象到着色器程序。program:指定要附加着色器的程序对象的标识符;shader:指定要附加的着色器对象的标识符。 -
void glLinkProgram(GLuint program)
用于将可编程渲染管道(OpenGL Shading Language)的顶点和片段着色器程序连接到一个可执行的程序对象中。如果连接成功,函数将返回 GL_TRUE,否则返回 GL_FALSE。 -
glGenVertexArrays & glGenBuffers 用于创建顶点数组对象(Vertex Array Object,VAO)和顶点缓冲对象(Vertex Buffer Object,VBO),并将顶点数据发送到 GPU。这两个函数可以将顶点数据从 CPU 发送到 GPU,这样 GPU 就可以在渲染过程中直接访问这些数据,而不是每次都从 CPU 获取数据。
关于OpenGL ES 3.2 API 的详细用法,可以参考:
2. OpenGLES Demo
2.1 简介
bianbu-linux 上的源码位置:xxx/bianbu-linux/package-src/k1x-gpu-test/openGLDemo
bianbu-desktop 上可以安装 k1x-gpu-test 来获取相关demo:sudo apt install k1x-gpu-test
目录结构如下:
.
|-- CMakeLists.txt //cmake文件,用于编译构建
|-- README.md
|-- common
| |-- include //头文件
| | |-- stb_image.h //单头文件图像加载库
| | |-- utils_opengles.h
| | `-- xdg-shell-client-protocol.h
| `-- source
| |-- utils_opengles.c //对egl等函数调用的封装
| `-- xdg-shell-protocol.c //xdg-shell协议
|-- cube_demo.c //立方体旋转
|-- cube_externalTexture_demo.c //立方体外部纹理贴图
|-- cube_texture_demo.c //立方体2D纹理贴图
|-- data //2D图片文件
| |-- bianbu.png
| `-- bianbu2.png
|-- square_demo.c //矩形
|-- texture_square_rotation_demo.c //2D纹理+旋转渲染的矩形
`-- triangle_demo.c //三角形
4 directories, 15 files