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 GLFW
    if (!glfwInit()) {
        fprintf(stderr, "Failed to initialize GLFW\n");
        return -1;
    }

    // Create a windowed mode window and its OpenGL context
    GLFWwindow* 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 current
    glfwMakeContextCurrent(window);

    // Load the OpenGL ES functions
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // Create and compile the vertex shader
    GLint status;
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexSource, NULL);
    glCompileShader(vertexShader);
    // Check for compilation errors
    if (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 shader
    GLuint 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 program
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    // Specify the layout of the vertex data
    GLfloat 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 data
    glUseProgram(shaderProgram);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
    glEnableVertexAttribArray(0);

    // Main loop
    while (!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 screen
        glClear(GL_COLOR_BUFFER_BIT);

        // Draw the triangle
        glUseProgram(shaderProgram);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glEnableVertexAttribArray(0);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        // Swap front and back buffers
        glfwSwapBuffers(window);
        // Poll for and process events
        glfwPollEvents();
    }

    // Clean up
    glDeleteBuffers(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 code
    const 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 code
    const 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 object
    userData->programObject = programObject;
    return GL_TRUE;
}

static int drawLoopInternal(ESContext* esContext) {
    // Vertex data
    GLfloat vertices[] = {
            0.0f,  0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f
    };

    // Set the viewport
    glViewport(0, 0, 640, 480);

    UserData *userData = esContext->userData;
    glUseProgram(userData->programObject);

    // Clear the color buffer
    glClearColor(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 triangle
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // Swap buffers
    eglSwapBuffers(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 display
    EGLint 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 window
    Window 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 EGL
    EGLDisplay 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 config
    EGLint 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 list
            EGL_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 surface
    EGLSurface 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 context
    EGLint 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 current
    if (!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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python3.6ssl证书错误无法pip的问题

出现了这个报错&#xff1a; Could not fetch URL https://pypi.python.org/simple/cryptography/: There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:748) - skipping 一开始以为是fiddler开着的原…

iOS——分类、扩展和关联对象

前情回顾 回顾一下什么是分类、什么是扩展&#xff1a; 分类&#xff08;Category&#xff09;和类扩展&#xff08;Extension&#xff09;是两种常见的代码组织方式&#xff0c;用于扩展类的功能。 分类&#xff08;Category&#xff09; 分类是一种将类的实现分散到多个源…

svn的使用

【图文详解】入职必备——SVN使用教程-CSDN博客 使用SVNBucket作为服务端,来辅助学习. 什么时候会产生冲突呢? 原本A,B,服务器的版本都一致,都是最新版. A修改文件m,向服务器提交 B修改文件m,向服务器提交,这时候出现了冲突 双击冲突的文件,手动修改

vscode 访问容器的方式

方法一&#xff1a;先连服务器&#xff0c;再转入容器 配置客户机A M1. 客户机A通过 vscode 连接服务器B&#xff0c;再连接容器C 配置vscode的ssh配置文件&#xff1a;~.ssh\config&#xff08;当需要多个不同的连接时&#xff0c;使用 IdentityFile 指定公钥位置&#xff09;…

【解决问题】QApplication: No such file or directory,C++ 使用Qt或项目未正确加载Cmake报错

运行环境&#xff1a; Clion编译&#xff0c;构建C工程项目报错QApplication: No such file or directory 问题描述 QApplication: No such file or directory 引用的#include <QApplication>飘红 解决方案 1、Qt没有安装正确&#xff0c;请使用对应版本的Qt。或编译…

【Java】Java流中的API

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

Vue笔记(二)

Vue&#xff08;一&#xff09;&#xff1a;Vue笔记&#xff08;一&#xff09;-CSDN博客 综合案例&#xff1a;水果购物车 项目功能&#xff1a; 视频链接&#xff1a;034-水果购物车-基本渲染_哔哩哔哩_bilibili 目录结构&#xff1a; index.css .app-container {padding-…

【python】flask 框架

python flask 框架 flask是一个轻量级的python后端框架 (Django, tornado, flask) 官网&#xff1a;欢迎来到 Flask 的世界 — Flask中文文档(3.0.x) 安装&#xff1a;pip install Flask -i https://pypi.douban.com 常识&#xff1a; http,默认端口号为80; https,默认端口号…

【Linux】进程间通信之命名管道

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

linux centos如何安装python3版本但不能影响默认python2版本

在CentOS上安装Python3而不影响系统默认的Python2,具有如何安装呢? 1. 更新系统包 首先,确保系统包是最新的: sudo yum update -y2. 安装EPEL存储库 EPEL(Extra Packages for Enterprise Linux)存储库包含许多额外的软件包,包括Python3: sudo yum install epel-rel…

IDEA:配置Golang的开发环境

1、下载&安装 进入GO的官网下载对应的GO 我们可以下载安装版&#xff0c;不过本人习惯下载解压版&#xff0c;这个因个人而异 2、配置环境变量 GOBIN : %GOROOT%\bin GOPATH : D:\MyGo 工作区间 GOROOT : D:\Program Files\Go GOJDK地址PATH: %GOBIN% ; %GOROOT%\bin ; …

LeetCode 算法:矩阵置零c++

原题链接&#x1f517;&#xff1a;矩阵置零 难度&#xff1a;中等⭐️⭐️ 题目 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1…

stm32MP135裸机编程:修改基于SD卡的FSBL-A用户程序引导程序(boot)

0 参考资料 轻松使用STM32MP13x - 如MCU般在cortex A核上裸跑应用程序.pdf stm32mp135官方开发板原理图&#xff08;mb1635-bdp-v1-0.zip&#xff09; STM32Cube_FW_MP13_V1.0.0 STM32CubeIDE v1.15 1 为什么需要修改FSBL-A用户程序引导程序 FSBL-A用户程序引导程序的作用在《…

PR如何让音频淡入淡出

PR如何让音频淡入淡出 方法一&#xff1a;效果控件关键帧方法二&#xff1a;音频轨道关键帧 以淡入为例&#xff0c;介绍如何设置淡入的两种方法&#xff0c;推荐使用第二种。淡出效果类似。 方法一&#xff1a;效果控件关键帧 选中音频&#xff0c;点击效果控件 在淡入结束的…

Gradio.NET 的简单入门使用

1、最近在网络上由发现了一个好完的东西。 2、Gradio.NET通过简单的C# Web API几行代码就可以实现一网页界面。 3、Python中也有一个Gradio&#xff0c;功能好像都差不多哦&#xff0c;不废话了&#xff0c;我们来开始实操。 4、在Visual Studio 2022 中创建一个 ASP.NET Cro…

Kimichat使用案例012:用Kimichat拆解雷军在小米汽车SU7发布会上的演讲技巧

文章目录 一、介绍二、输入内容三、输出内容四、继续追问五、继续回答六、讲解对比七、对比回答相似之处:不同之处:八、职场人士如何借鉴九、借鉴内容一、介绍 小米SU7发布会可以说是非常成功。雷军的演讲技巧是发布会成功的重要因素之一,很值得借鉴学习。 可以借助Kimichat…

dat.gui图形用户页面

一、导入 1.npm安装 npm install --save dat.gui 引入&#xff1a; // CommonJS: const dat require(dat.gui); // ES6: import * as dat from dat.gui; const gui new dat.GUI(); 二、控制器 <!DOCTYPE html> <html lang"en"> <head><…

振动分析-1-频谱分析的关键步骤及如何看频谱图

振动故障诊断——如何进行振动频谱分析 参考振动频谱分析关键步骤及分析要点 参考怎么看频谱图? 图解滚动轴承故障的频谱波形 1 频谱分析关键步骤 频谱分析准确与否取决于多个方面。 (1)设置仪器频率范围、分辨率等&#xff1b; (2)数据采集位置应根据设备的机械特性、振动传…

Qt——升级系列(Level Five):显示类控件、输入类控件、多元素控件、容器类控件、布局管理器

显示类控件 Label QLabel 可以⽤来显⽰⽂本和图⽚. 核⼼属性如下&#xff1a; 属性 说明 text QLabel 中的⽂本 textFormat ⽂本的格式. • Qt::PlainText 纯⽂本 • Qt::RichText 富⽂本(⽀持 html 标签) • Qt::MarkdownText markdown 格式 • Qt::AutoText 根…

matlab演示银河系转动动画

代码 function GalaxyRotationSimulation()% 参数设置num_stars 1000; % 恒星数量galaxy_radius 1; % 银河系半径rotation_speed 0.05; % 旋转速度% 生成银河系中的恒星分布theta 2 * pi * rand(num_stars, 1); % 角度r galaxy_radius * sqrt(rand(num_stars, 1)); % 半径…