哪家做网站的比较好,友情链接格式,wordpress 好主题哦,网站服务器类型OpenGL-ES Ubuntu 环境搭建
此的方法在 ubuntu 和 deepin 上验证都可以成功搭建 目录 OpenGL-ES Ubuntu 环境搭建软件包安装第一个三角形基于 glfw 实现基于 X11 实现 软件包安装
sudo apt install libx11-dev
sudo apt install libglfw3 libglfw3-dev
sudo apt-get install…OpenGL-ES Ubuntu 环境搭建
此的方法在 ubuntu 和 deepin 上验证都可以成功搭建 目录 OpenGL-ES Ubuntu 环境搭建软件包安装第一个三角形基于 glfw 实现基于 X11 实现 软件包安装
sudo apt install libx11-dev
sudo apt install libglfw3 libglfw3-dev
sudo apt-get install libgles2-mesa
sudo apt-get install libgles2-mesa-dev检查环境是否安装成功 /usr/include 下是否有 EGL GL GLES2 GLES3 的目录
Note: 上面的环境中同时安装了 x11 和 glfw实际上只需要安装一个自己需要的即可, x11 和 glfw 都是为 OES 环境对接到窗口系统中 个人觉得 x11 的API 对 egl 的封装比较标准话一些可以用于学习 egl 的api
第一个三角形
基于 glfw 实现
#include stdio.h
#include time.h
#include GLES2/gl2.h
#include GLFW/glfw3.h// Vertex Shader source code
// Vertex Shader source code
const GLchar* vertexSource #version 300 es\nlayout(location 0) in vec4 position;\nvoid main() {\n gl_Position position;\n}\n;// Fragment Shader source code
const GLchar* fragmentSource #version 300 es\nprecision mediump float;\nout vec4 fragColor;\nvoid main() {\n fragColor vec4(1.0, 0.0, 0.0, 1.0);\n}\n;int main() {printf(main testsuites enter n);// Initialize GLFWif (!glfwInit()) {fprintf(stderr, Failed to initialize GLFW\n);return -1;}// Create a windowed mode window and its OpenGL contextGLFWwindow* window glfwCreateWindow(640, 480, opengles-glfw, NULL, NULL);if (!window) {fprintf(stderr, Failed to create GLFW window\n);glfwTerminate();return -1;}// Make the windows context currentglfwMakeContextCurrent(window);// Load the OpenGL ES functionsglClearColor(0.0f, 0.0f, 0.0f, 1.0f);// Create and compile the vertex shaderGLint status;GLuint vertexShader glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, vertexSource, NULL);glCompileShader(vertexShader);// Check for compilation errorsif (status ! GL_TRUE) {char buffer[512];glGetShaderInfoLog(vertexShader, 512, NULL, buffer);fprintf(stderr, Vertex Shader Compile Error: %s\n, buffer);}// Create and compile the fragment shaderGLuint fragmentShader glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, fragmentSource, NULL);glCompileShader(fragmentShader);glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, status);if (status ! GL_TRUE) {char buffer[512];glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);fprintf(stderr, Fragment Shader Compile Error: %s\n, buffer);}// Link the vertex and fragment shader into a shader programGLuint shaderProgram glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);// Specify the layout of the vertex dataGLfloat vertices[] {0.0f, 0.5f, 0.0f,0.5f, -0.5f, 0.0f,-0.5f, -0.5f, 0.0f,};GLuint vbo;glGenBuffers(1, vbo);glBindBuffer(GL_ARRAY_BUFFER, vbo);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// Specify the layout of the vertex dataglUseProgram(shaderProgram);glBindBuffer(GL_ARRAY_BUFFER, vbo);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);glEnableVertexAttribArray(0);// Main loopwhile (!glfwWindowShouldClose(window)) {// calculate for extecute time,about 16.6ms every period{struct timespec currentts;static uint64_t timeInMiliSeconds 0;clock_gettime(CLOCK_REALTIME, currentts);uint64_t currentMilliseconds currentts.tv_sec * 1000LL currentts.tv_nsec / 1000000;int periodInMs currentMilliseconds - timeInMiliSeconds;timeInMiliSeconds currentMilliseconds;printf(current time in milliseconds %lld period:%d\n, currentMilliseconds,(periodInMs 0 ? periodInMs : -1));}// Clear the screenglClear(GL_COLOR_BUFFER_BIT);// Draw the triangleglUseProgram(shaderProgram);glBindBuffer(GL_ARRAY_BUFFER, vbo);glEnableVertexAttribArray(0);glDrawArrays(GL_TRIANGLES, 0, 3);// Swap front and back buffersglfwSwapBuffers(window);// Poll for and process eventsglfwPollEvents();}// Clean upglDeleteBuffers(1, vbo);glDeleteProgram(shaderProgram);glDeleteShader(vertexShader);glDeleteShader(fragmentShader);glfwDestroyWindow(window);glfwTerminate();return 0;
}基本步骤如下 GLFW初始化和窗口创建 初始化GLFW并设置OpenGL ES上下文版本 创建窗口并设置上下文将创建的窗口用于opengl-es上下文此时opengl-es和系统的窗口系统相关联 , 创建着色器编译着色器最近将其链接到一个程序对象 编译顶点着色器和片段着色器并将它们链接到一个程序中 定义一个简单的三角形顶点数据并绘制三角形 设置视口清除颜色缓冲区加载顶点数据并调用绘制命令 主循环中不断交换缓冲区并处理事件以保持窗口响应。 删除程序和着色器销毁窗口并终止GLFW
对应的 CMakeLists.txt 实现
cmake_minimum_required(VERSION 3.27)
project(opengles_glfw C)set(CMAKE_C_STANDARD 11)find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)include_directories(${GLFW_INCLUDE_DIRS})add_executable(opengles_glfw main.c)
target_link_libraries(opengles_glfw ${GLFW_LIBRARIES} GLESv2)
在程序主循环中还添加了计时相关的代码逻辑在glfw 的模式下主循环也是跟屏幕刷新率相同也是60Hz, 可以看到每次循环体的执行间隔都是 16.6ms
current time in milliseconds 1717986851291 period:14
current time in milliseconds 1717986851308 period:17
current time in milliseconds 1717986851324 period:16基于 X11 实现
基于 X11 实现的 opengl-es 环境如下
#include malloc.h
#include glesbasicTriangle.htypedef struct {GLuint programObject;
} UserData;static int initInternal(ESContext* esContext) {UserData *userData esContext-userData;// Vertex Shader source codeconst char* vertexShaderSource #version 300 es \nlayout(location 0) in vec4 a_position; \nvoid main() {\n gl_Position a_position;\n}\n;// Fragment Shader source codeconst char* fragmentShaderSource #version 300 es \nprecision mediump float;\nlayout(location 0) out vec4 outColor; \nvoid main() {\n outColor vec4(1.0, 0.0, 0.0, 1.0);\n}\n;// 这里封装了 createshader-compilershader-createprogramobject-link programoobject 的操作GLuint programObject esLoadProgram(vertexShaderSource, fragmentShaderSource);if (programObject 0) {return GL_FALSE;}// Store the program objectuserData-programObject programObject;return GL_TRUE;
}static int drawLoopInternal(ESContext* esContext) {// Vertex dataGLfloat vertices[] {0.0f, 0.5f, 0.0f,-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f};// Set the viewportglViewport(0, 0, 640, 480);UserData *userData esContext-userData;glUseProgram(userData-programObject);// Clear the color bufferglClearColor(0.0, 0.0, 0.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);glEnableVertexAttribArray(0);// Draw the triangleglDrawArrays(GL_TRIANGLES, 0, 3);// Swap bufferseglSwapBuffers(esContext-eglDisplay, esContext-eglSurface);
}static int cleanupInternal(ESContext* esContext) {printf(%s enter!.\n,__FUNCTION__);UserData *userData esContext-userData;glDeleteProgram(userData-programObject);eglDestroySurface(esContext-eglDisplay, esContext-eglSurface);eglDestroyContext(esContext-eglDisplay, esContext-eglContext);eglTerminate(esContext-eglDisplay);XDestroyWindow(esContext-x_display, esContext-win);XCloseDisplay(esContext-x_display);return GL_TRUE;
}int testbasicDrawTriangle(ESContext* esContext) {printf(%s enter!.\n, __FUNCTION__);esContext-userData (UserData*)malloc(sizeof(UserData));initInternal(esContext);while (1) {XEvent xev;while (XPending(esContext-x_display)) {XNextEvent(esContext-x_display, xev);if (xev.type KeyPress) {cleanupInternal(esContext);}}drawLoopInternal(esContext);}}其中在调用 testbasicDrawTriangle 之前, 还有窗口系统的准备工作需要完成实现就是下面的函数esCreateWindow 其他文件中实现 main 函数在调用 testbasicDrawTriangle 之前就已经调用了 esCreateWindow 函数
GLboolean esCreateWindow ( ESContext *esContext, const char *title, GLint width, GLint height, GLuint flags )
{
// Open X11 displayEGLint majorVersion;EGLint minorVersion;Display* x_display XOpenDisplay(NULL);if (x_display NULL) {printf(Failed to open X display\n);return GL_FALSE;}esContext-x_display x_display;esContext-width width;esContext-height height;// Create X11 windowWindow root DefaultRootWindow(esContext-x_display);XSetWindowAttributes swa;swa.event_mask ExposureMask | PointerMotionMask | KeyPressMask;Window win XCreateWindow(esContext-x_display, root,0, 0, width, height, 0,CopyFromParent, InputOutput,CopyFromParent, CWEventMask,swa);XMapWindow(esContext-x_display, win);XStoreName(esContext-x_display, win, title);esContext-win win;// Initialize EGLEGLDisplay egl_display eglGetDisplay((EGLNativeDisplayType)esContext-x_display);if (egl_display EGL_NO_DISPLAY) {printf(Failed to get EGL display\n);return GL_FALSE;}esContext-eglDisplay egl_display;if (!eglInitialize(esContext-eglDisplay, majorVersion, minorVersion)) {printf(Failed to initialize EGL\n);return GL_FALSE;}printf(%s majorVersion:%d minorVersion:%d \n, __FUNCTION__, majorVersion, minorVersion);// Choose an EGL configEGLint configAttribs[] {EGL_SURFACE_TYPE, EGL_WINDOW_BIT,EGL_BLUE_SIZE, 8,EGL_GREEN_SIZE, 8,EGL_RED_SIZE, 8,EGL_DEPTH_SIZE, 8,EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,EGL_NONE};EGLint attribList[] {EGL_RED_SIZE, 5,EGL_GREEN_SIZE, 6,EGL_BLUE_SIZE, 5,EGL_ALPHA_SIZE, ( flags ES_WINDOW_ALPHA ) ? 8 : EGL_DONT_CARE,EGL_DEPTH_SIZE, ( flags ES_WINDOW_DEPTH ) ? 8 : EGL_DONT_CARE,EGL_STENCIL_SIZE, ( flags ES_WINDOW_STENCIL ) ? 8 : EGL_DONT_CARE,EGL_SAMPLE_BUFFERS, ( flags ES_WINDOW_MULTISAMPLE ) ? 1 : 0,// if EGL_KHR_create_context extension is supported, then we will use// EGL_OPENGL_ES3_BIT_KHR instead of EGL_OPENGL_ES2_BIT in the attribute listEGL_RENDERABLE_TYPE, GetContextRenderableType ( esContext-eglDisplay ),EGL_NONE};EGLConfig egl_config;EGLint numConfigs;eglChooseConfig(esContext-eglDisplay, attribList, egl_config, 1, numConfigs);if (numConfigs ! 1) {printf(Failed to choose EGL config\n);return GL_FALSE;}// Create an EGL window surfaceEGLSurface egl_surface eglCreateWindowSurface(esContext-eglDisplay, egl_config, (EGLNativeWindowType)esContext-win, NULL);if (egl_surface EGL_NO_SURFACE) {printf(Failed to create EGL surface\n);return GL_FALSE;}esContext-eglSurface egl_surface;// Create an EGL contextEGLint contextAttribs[] { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };EGLContext egl_context eglCreateContext(esContext-eglDisplay, egl_config, EGL_NO_CONTEXT, contextAttribs);if (egl_context EGL_NO_CONTEXT) {printf(Failed to create EGL context\n);return GL_FALSE;}esContext-eglContext egl_context;// Make the context currentif (!eglMakeCurrent(esContext-eglDisplay, esContext-eglSurface , esContext-eglSurface , esContext-eglContext)) {printf(Failed to make EGL context current\n);return GL_FALSE;}return GL_TRUE;
}
在 esCreateWindow 的代码中使用 x_display 关联到了 egl 的display 对象中同时使用在 eglCreateWindowSurface 中 使用了 x11 创建的 win handle 创建 EGLSurface
其余绘制三角形的步骤和 glfw 的基本一致 实现效果如下