OpenGL-ES 学习(6)---- Ubuntu OES 环境搭建

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\n""layout(location = 0) in vec4 position;\n""void main() {\n""    gl_Position = position;\n""}\n";// Fragment Shader source code
const GLchar* fragmentSource ="#version 300 es\n""precision mediump float;\n""out vec4 fragColor;\n""void 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 window's 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;
}

基本步骤如下:

  1. GLFW初始化和窗口创建
    初始化GLFW并设置OpenGL ES上下文版本
    创建窗口并设置上下文,将创建的窗口用于opengl-es上下文,此时opengl-es和系统的窗口系统相关联 , 创建着色器,编译着色器,最近将其链接到一个程序对象

  2. 编译顶点着色器和片段着色器,并将它们链接到一个程序中

  3. 定义一个简单的三角形顶点数据,并绘制三角形

  4. 设置视口,清除颜色缓冲区,加载顶点数据,并调用绘制命令

  5. 主循环中不断交换缓冲区并处理事件,以保持窗口响应。

  6. 删除程序和着色器,销毁窗口,并终止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.h"typedef struct {GLuint programObject;
} UserData;static int initInternal(ESContext* esContext) {UserData *userData = esContext->userData;// Vertex Shader source codeconst char* vertexShaderSource ="#version 300 es                            \n""layout(location = 0) in vec4 a_position;   \n""void main() {\n""   gl_Position = a_position;\n""}\n";// Fragment Shader source codeconst char* fragmentShaderSource ="#version 300 es                            \n""precision mediump float;\n""layout(location = 0) out vec4 outColor;             \n""void 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 的基本一致
实现效果如下:
basic_triangles

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/25611.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

​2020-2024 idea最新安装激活

前言&#xff1a;怎么才能既免费&#xff0c;又能使用上正式版呢&#xff01;&#xff08;不是正版用不起&#xff0c;而是‘激活’更有性价比&#xff09; 1-2 下载安装&#xff0c;此处省略 记得安装好不要打开&#xff0c;看下一步。 3.开始 3.1打开idea 首先打开idea&am…

Dish-TS: 缓解分布转移的一般范例 时间序列预测

摘要 时间序列预测(TSF)中的分布移位(即序列分布随时间的变化)在很大程度上阻碍了TSF模型的性能。现有的关于时间序列中分布变化的研究大多局限于分布的量化&#xff0c;更重要的是&#xff0c;忽视了回望窗和地平线窗之间的潜在变化。为了应对上述挑战&#xff0c;我们系统地…

VM-Import 导入 Debian 12 系统

介绍 之前介绍过使用 VM-Import 导入 Windows 系统到 AWS 环境启动 EC2 实例, 本文将介绍如何导入 Debian 12 系统. 本地虚拟化使用 VMWare Workstation 创建虚拟机安装和准备 Debian 12 系统, 导出 OVA 文件后上传到 S3 存储桶中再使用 AWSCLI 执行 VM-Import 命令实现导入过…

【Vue】获取模块内的state数据

目标&#xff1a; 掌握模块中 state 的访问语法 尽管已经分模块了&#xff0c;但其实子模块的状态&#xff0c;还是会挂到根级别的 state 中&#xff0c;属性名就是模块名 使用模块中的数据 直接通过模块名访问 $store.state.模块名.xxx 通过 mapState 映射&#xff1a; 默认…

mac免费的ntfs软件哪个好 MAC读取NTFS硬盘格式

对于苹果用户来说&#xff0c;Mac电脑和移动硬盘已经成为日常工作中不可缺少的一部分&#xff0c;但有时我发现Mac打开移动硬盘只能读取无法写入&#xff0c;这是由于所连接的移动硬盘为NTFS格式。我们可以通过对硬盘格式化为Mac正常读写格式&#xff0c;或使用数据读写软件对N…

DNS协议 | NAT技术 | 代理服务器

目录 一、DNS协议 1、DNS背景 2、DNS协议 域名 域名解析 二、NAT技术 1、NAT技术 2、NAPT技术 3、NAT技术的缺陷 三、代理服务器 1、正向代理服务器 2、反向代理服务器 一、DNS协议 域名系统&#xff08;Domain Name System&#xff0c;缩写&#xff1a;DNS&#…

Zabbix配置中文显示及乱码问题

页面配置为中文显示 在zabbix 5.0版本开始用户菜单更改为左侧栏显示&#xff0c;找到并点击 User Settings&#xff0c;Language 修改语言为 Chinese (zh_CN) 即可。 PS&#xff1a;一般在部署后初始配置时&#xff0c;未找到 Chinese (zh_CN) 这一项&#xff0c;修改如下&…

深度学习中embedding层的理解

Embedding层作用 在深度学习领域中&#xff0c;Embedding层扮演着至关重要的角色&#xff0c;尤其在处理文本数据或类别数据。Embedding层的功能有两个&#xff1a; 1. 将高维稀疏的输入数据&#xff08;如单词、类别标签等&#xff09;转换为低维稠密的向量表示&#xff0c;…

数 据 类 型

概述 Java 是强类型语言。 每一种数据都定义了明确的数据类型&#xff0c;在内存中分配了不同大小的内存空间&#xff08;字节&#xff09;。 Java 中一共有 8 种基本类型&#xff08;primitive type&#xff09;&#xff0c;包括 4 种整型、2 种浮点型、1 种字符类型&#…

Vulnhub靶机之reven 1

一、信息收集 nmap扫描网段&#xff0c;靶机地址为192.168.145.129。 nmap -sP 192.168.145.* 扫一下端口&#xff0c;开放了22、80、111、50967。 nmap -sT -T4 -p1-65535 192.168.145.129 再看一下目录情况&#xff0c;发现一个疑似后台登录的地址。 dirsearch -u http://…

【C++修行之道】类和对象(六)再谈构造函数(初始化列表)| explicit关键字 | static成员 | 友元|匿名对象|拷贝时一些编译器优化

目录 一、再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1. 所有的成员,既可以在初始化列表初始化,也可以在函数体内初始化 2. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次) 3. 类中包含以下成员&#xff0c;必须放在初始化列表位置进行初始化&…

N32G45XVL-STB之移植LVGL(lvgl-8.2.0)

目录 概述 1 软硬件介绍 1.1 软件版本信息 1.2 ST7796-LCD 1.3 MCU IO与LCD PIN对应关系 2 认识LVGL 2.1 LVGL官网 2.2 LVGL库文件下载 3 移植LVGL 3.1 准备移植文件 3.2 添加lvgl库文件到项目 3.2.1 src下的文件 3.2.2 examples下的文件 3.2.3 配置文件路径 3.2…

VS2019专业版 C#和MFC安装

1. VS2019专业版下载地址 https://learn.microsoft.com/en-us/visualstudio/releases/2019/history 2.安装 C# 部分 MFC部分

【Linux】进程6——环境变量

1.什么是环境变量 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 比如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪里&#xff0c;但是照样可以链接成功&…

通过 Python+Nacos实现微服务,细解微服务架构

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 背景 一直以来的想法比较多&#xff0c;然后就用Python编写各种代码脚本。很多…

这个国际档案日,大比武放榜、直播预约、课件下载,一样都不能少!

关注我们 - 数字罗塞塔计划 - 2024年6月9日第十七个国际档案日来临&#xff0c;数字罗塞塔计划放大招&#xff1a;第二届大比武活动榜单揭晓、ARCHE-2024上海智慧档案高峰论坛直播预约、2024上半年度课件大礼包下载。如此大礼&#xff0c;岂能错过&#xff1f; PART.01 榜单…

【LeetCode 第 401 场周赛】K秒后第 N 个元素的值

文章目录 1. K秒后第 N 个元素的值&#x1f197; 1. K秒后第 N 个元素的值&#x1f197; 题目链接&#x1f517; &#x1f427;解题思路&#xff1a; 前缀和 小规律&#x1f34e; &#x1f34e; 从上图观察可知&#xff0c;规律一目了然&#xff0c;arr[i] arr[i] 对上一…

2024-6-9

今日安排&#xff1a; 学校的课程作业windows SEH 机制简单入门windows 用户态 pwn / 内核态入门 计网实验报告 && 网安实验报告继续审计 nf_tables 源码&#xff0c;主要看 active 相关逻辑。复现 CVE-2022-32250 这个漏洞【 && iptables 相关学习】♥♥♥♥…

基于vue的音乐播放器的设计与实现(论文+源码)_kaic

摘 要 当下&#xff0c;如果还依然使用纸质文档来记录并且管理相关信息&#xff0c;可能会出现很多问题&#xff0c;比如原始文件的丢失&#xff0c;因为采用纸质文档&#xff0c;很容易受潮或者怕火&#xff0c;不容易备份&#xff0c;需要花费大量的人员和资金来管理用纸质文…

【Qt秘籍】[010]-Qt常用控件

一、控件概述 在GUI&#xff08;图形用户界面&#xff09;开发领域&#xff0c;Qt无疑是众多开发者心中的首选框架之一。它不仅跨平台、功能强大&#xff0c;而且拥有丰富且灵活的控件库&#xff0c;使得开发者能够快速构建美观、高效的用户界面。对于初学者而言&#xff0…