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

news2024/10/7 6:38:46

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

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

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

相关文章

WPF学习(3)--不同类通过接口实现同种方法

一、接口概述 1.接口的概念 在C#中&#xff0c;接口&#xff08;interface&#xff09;是一种引用类型&#xff0c;它定义了一组方法、属性、事件或索引器&#xff0c;但不提供实现。接口只定义成员的签名&#xff0c;而具体的实现由实现接口的类或结构体提供。接口使用关键字…

Tita 360评估:有效 360度反馈流程的 10 大步骤

宣传过程 如果你的公司首次引入多方位反馈或 360 度反馈&#xff0c;那么向所有利益相关者描述这一流程至关重要。由于流程太新&#xff0c;很多人还不了解。确保参与该流程的每个人都了解其目的&#xff0c;以及将如何实施该流程和使用其结果。花时间在一对一会议、小组会议和…

6.每日LeetCode-数组类,找到所有数组中消失的数字(Go)

题目 448找到所有数组中消失的数字.go 给你一个含 n 个整数的数组 nums &#xff0c;其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字&#xff0c;并以数组的形式返回结果。 示例 1&#xff1a; 输入&#xff1a;nums [4,3,2,7,8,2,…

后仿真中《SDF反标必懂连载篇》之 <INTERCONNECT/IOPATH> 庐山面目

对于SDF INTERCONNECT ENTRY 描述&#xff0c;我们在之前的文章有详解。 读万卷书&#xff0c;行万里路。 实践很重要。 今天&#xff0c;搞一下SDF INTERCONNECT / IOPATH 延迟数据信息&#xff0c;究竟反标的是哪一路径延时&#xff1f; 一 IOPATH (CELL(CELLTYPE …

STM32F103C8T6 IAP升级

目录 0x00 前言0x01 flash分区0x02 Bootloader0x02 APP设置0x03 升级程序编写0x04 固件烧录 0x00 前言 STM32有三种烧录程序的方式&#xff1a;烧录器下载、拉高boot1进行串口下载(ISP)还有通过在 Bootloader中进行flash擦除和写入(IAP)。 在进行开发之前&#xff0c;你需要了…

上海晋名室外危废品暂存柜助力储能电站行业危废品安全储存

近日又有一台SAVEST室外危废暂存柜项目成功验收交付使用&#xff0c;此次项目主要用于储能电站行业废油、废锂电池等危废品的安全储存。 用户单位在日常工作运营中涉及到废油、废锂电池等危废品的室外安全储存问题。4月中旬用户技术总工在寻找解决方案的过程中搜索到上海晋名的…

蒂姆·库克解释Apple Intelligence和与ChatGPT合作的区别|TodayAI

在2024年全球开发者大会&#xff08;WWDC 2024&#xff09;上&#xff0c;苹果公司首席执行官蒂姆库克&#xff08;Tim Cook&#xff09;隆重介绍了公司的最新人工智能&#xff08;AI&#xff09;计划——Apple Intelligence&#xff0c;并宣布了与OpenAI的ChatGPT的合作。虽然…

突破管理瓶颈:基于前端技术的全面预算编制系统解析

前言 在现代商业环境中&#xff0c;预测销售数据和实际成本是每个公司CEO和领导都极为重视的关键指标。然而&#xff0c;由于市场的不断变化&#xff0c;准确地预测和管理这些数据变得愈发具有挑战性。为了应对这一挑战&#xff0c;建立一个高效的系统来管理和审查销售数据的重…

展位展台设计要注意的问题

1、选择专业的展台设计公司 特装比一般展位设计更要保证展台的独特性&#xff0c;更具可塑性。任何疑问和要求都能得到专业的解答。不论是展台的整体结构&#xff0c;还是展台搭建材料&#xff0c;都能实现良好的沟通&#xff0c;两方面都可以确保参加展会的双赢。 2、缜密的展…

智能家居建材,打造未来家居生活

智能家居建材&#xff0c;正引领着家居行业的新潮流。它融合了先进的科技与人性化的设计&#xff0c;为我们打造了一个充满未来感的家居新体验。 想象一下&#xff0c;当你走进家门&#xff0c;智能门锁自动识别你的身份&#xff0c;轻轻一推即可进入。室内环境自动调节到最舒适…

生成式人工智能 - 本地windows 11 + PyCharm运行stable diffusion流程简述

一、环境说明 硬件:本地电脑windows11、32.0 GB内存、2060的6G的卡。 软件:本地有一个python环境,主要是torch 2.2.2+cu118 二、准备工作 1、下载模型 https://huggingface.co/CompVishttps://huggingface.co/CompVis 进入上面的网址,我这里下载的是这个里面的 …

达到1k stars后,我对大模型开源教程的反思!(附教程)

前 言 “五一”节后第一个开心的消息是我们开源的大模型基础项目(https://github.com/datawhalechina/so-large-lm)已经达到1k stars⭐️了。这个开源项目是为了提供浅显易懂且前沿的大模基础知识而打造的&#xff0c;能收获1k个stars⭐️也是对这个项目的肯定。我为一起付出努…

软考初级网络管理员_07_网络单选题

1.观察交换机状态指示灯初步判断交换机故障&#xff0c;交换机运行中指示灯显示红色表示()。 警告 正常 待机 繁忙 2.通常测试网络连通性采用的命令是()。 Netstat Ping Msconfig Cmd 3.一台16端口的交换机可以产生&#xff08;&#xff09;个冲突域? 1 4 15 16…

诊所管理系统如何重塑患者就医流程

随着信息技术的快速发展&#xff0c;诊所管理系统的应用正在为医疗服务带来革命性的变化。这一系统不仅仅是一种管理工具&#xff0c;更是一种全方位的健康管理解决方案&#xff0c;从诊前、诊中到诊后&#xff0c;为患者提供了一系列便捷、高效的服务&#xff0c;让患者的就医…

Java代码实现获取一个文件夹下所有文件名并输出到指定的txt文件中

当一个文件夹中文件过多时&#xff0c;且需要知道次序跟名称时&#xff0c;下面用一段Java代码来实现&#xff1a; 输出一个文件夹内所有的文件名并在前面标上序号&#xff0c;输出到一个文本文件中 最终效果 序号文件名列表 完整代码 import java.io.File; import java.i…

PostgreSql中使用to_char函数、date()函数可能会导致索引无法充分利用,导致查询速度无法提升

今天在处理接口请求速度慢的问题&#xff0c;惊奇的发现加了索引&#xff0c;但还是请求很忙。由于card_stop_info表有300w条数据&#xff0c;这时候关联查询非常慢&#xff0c;于是我加上匹配项索引&#xff0c;但是发现依然没有改变速度。。这时候去搜了一下才知道pgsql的to_…

随手记:uniapp图片展示,剩余的堆叠

UI效果图&#xff1a; 实现思路&#xff1a; 循环图片数组&#xff0c;只展示几张宽度就为几张图片边距的宽度&#xff0c;剩下的图片直接堆叠展示 点击预览的时候传入当前的下标&#xff0c;如果是点击堆叠的话&#xff0c;下标从堆叠数量开始计算 <template><…

比人工快100倍!给3D模型用上轻量化,老爷机也能起飞!!!!!!

3D可视化开发&#xff0c;考虑最多的要素&#xff0c;当属模型加载流畅度和应用性。但面对单位的电脑、不能升级硬盘的笔记本等&#xff0c;可能还是无法体会到模型丝滑加载的畅快。 况且3D模型数据、格式等&#xff0c;也在不断发展扩充&#xff0c;昔日手工就能“调教”的3D…

CSS Flexbox(弹性布局)

目录 &#x1f587;️什么是弹性布局&#xff1f; &#x1f587;️容器属性 ○ flex-direction ○ justify-content ○ align-items ○ flex-warp ○ align-content &#x1f587;️项目属性 ○ order ○ flex &#x1f587;️总结 提示: 如果你是小白&#xff0c;不…

CentOS7安装nginx【巨详细】

CentOS7安装nginx 安装依赖 1.安装gcc&#xff0c;nginx 编译时依赖 gcc 环境 # 安装c yum install gcc-c# 查看版本 gcc -v正常情况显示如下 2.安装openssl 安全套接字层密码库&#xff0c;用于通信加密 yum install -y openssl openssl-devel3.安装zlib,zlib 库 提供了很多…