OpenGL 是一种跨平台的图形 API,用于为 3D 图形处理硬件指定标准的软件接口。[OpenGL ES]是 OpenGL 规范的一种形式,适用于嵌入式设备。HarmonyOS 现已支持 OpenGL ES 3.2。
支持的能力
OpenGL ES 3.2
标准库中导出的符号列表
[native api中导出的OpenGL ES 3.2符号列表]
引入OpenGL能力
如果开发者需要使用OpenGL的相关能力,需要添加相关动态链接库和头文件。
添加动态链接库
CMakeLists.txt中添加以下lib。
libace_ndk.z.so
libace_napi.z.so
libGLESv3.so
libEGL.so
头文件
#include <ace/xcomponent/native_interface_xcomponent.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include <GLES3/gl3.h>
OpenGL ES扩展接口
- OpenGL ES扩展接口的官方参考文档:[OpenGL ES扩展接口]
- 开发者可以调用glGetString查询芯片厂商支持的扩展接口,调用之前务必初始化上下文,具体示例如下:
EGLDisplay display;
EGLConfig config;
EGLContext context;
EGLSurface surface;
EGLint majorVersion;
EGLint minorVersion;
EGLNativeWindowType win;
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, &majorVersion, &minorVersion);
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, &majorVersion, &minorVersion);
EGLint attribs[] = {
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
surface = eglCreatePbufferSurface(display, config, NULL);
eglMakeCurrent(display, surface, surface, context);
char *strTest = new char[1024];
strTest = (char *)glGetString(GL_EXTENSIONS); // 返回值strTest中会列出所有的扩展接口,并且用空格分隔开
bool isHave = strTest.find("GL_OES_matrix_palette") != -1 ?
true :
false; // 查询是否有某个扩展接口,有则isHave为true,没有则为false
简单示例
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <iostream>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
int main() {
// 初始化 EGL
EGLDisplay display;
EGLConfig config;
EGLContext context;
EGLSurface surface;
EGLint numConfigs;
EGLint majorVersion;
EGLint minorVersion;
// 初始化 EGL Display
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, &majorVersion, &minorVersion);
// 配置 EGL
EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_BLUE_SIZE, 6,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
// 创建 EGL Context
EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
// 创建 EGL Surface
surface = eglCreateWindowSurface(display, config, nativeWindow, NULL);
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
// 绑定 EGL Context 和 Surface
eglMakeCurrent(display, surface, surface, context);
// 设置视口大小
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
// 清除颜色缓冲
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 定义顶点数据
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f, // 左下角
0.5f, -0.5f, 0.0f, // 右下角
0.0f, 0.5f, 0.0f // 顶部
};
// 创建并绑定顶点缓冲对象
GLuint VAO[0];
GLuint VBO;
glGenVertexArrays(1, VAO);
glBindVertexArray(VAO[0]);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 创建着色器程序
const char* vertexShaderSource = R"(
#version 300 es
precision mediump float;
layout (location = 0) in vec3 aPos;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
)";
const char* fragmentShaderSource = R"(
#version 300 es
precision mediump float;
out vec4 FragColor;
void main() {
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
)";
GLuint vertexShader, fragmentShader, shaderProgram;
// 创建顶点着色器
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
// 创建片段着色器
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
// 创建着色器程序
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 使用着色器程序
glUseProgram(shaderProgram);
// 绑定顶点数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// 绘制三角形
glDrawArrays(GL_TRIANGLES, 0, 3);
// 交换缓冲区
eglSwapBuffers(display, surface);
// 清理
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteBuffers(1, &VBO);
// 等待退出
std::cout << "Press Enter to exit..." << std::endl;
std::cin.get();
// 清理 EGL
eglDestroyContext(display, context);
eglDestroySurface(display, surface);
eglTerminate(display);
return 0;
}
该示例首先使用了EGL创建了渲染表面,EGL可以用于管理绘图表面(window surface只是一种类型,还有pbuffer、pixmap)。下面详细地解释下每个步骤。