Ubuntu20.04+GLFW搭建OpenGL开发环境

news2024/11/17 10:45:09

环境

系统:Ubuntu 20.04
桌面环境:X11
OpenGL版本: 3.0

桌面环境怎么看呢?可以在终端输入echo $XDG_SESSION_TYPE 即可,或者查看桌面右上角的Settings->About,查看Windowing System

在这里插入图片描述

查看OpenGL版本

使用glxinfo命令查看,没安装需要安装mesa-utils工具,sudo apt install mesa-utils

$ glxinfo | grep OpenGL
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 4600 (HSW GT2)
OpenGL core profile version string: 4.5 (Core Profile) Mesa 21.2.6
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 21.2.6
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.1 Mesa 21.2.6
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10
OpenGL ES profile extensions:

上面OpenGL version string: 3.0 Mesa 21.2.6可以看出OpenGL的版本为3.0

开始安装

2.1 安装xorg依赖(GLFW的依赖)
# 前面我们的x11,所以需要安装下面依赖,若为其他wayland,则需要参考glfw官方编译指导进行,[点这里](https://www.glfw.org/docs/latest/compile_guide.html)
$ sudo apt install xorg-dev
2.2 安装GLFW

GLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体所需的最低限度的接口,允许用户创建OpenGL上下文、定义窗口参数以及处理用户输入
glfw官网

下载glfw源码进行编译

git clone https://github.com/glfw/glfw

编译

cd glfw
cmake -S . -B build
cd build
make

安装

sudo make install

完成GLFW的编译及安装

2.3 安装GLAD

由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用,取得地址的方法代码非常复杂,而且很繁琐,GLAD是一个开源的库,能解决这个繁琐的问题

前面我们知道OpenGl的版本为3.0,这里我们需要对号入座

# 再次查看一下OpenGL版本,没毛病,是3.0
glxinfo | grep "OpenGL version"
OpenGL version string: 3.0 Mesa 21.2.6

登录到GLAD官网,点这里

API->gl 处,选择OpenGL的版本3.0,其他不用修改,点击下面的GENERATE
在这里插入图片描述点击GENREATE后,进入如下页面

在这里插入图片描述下载glad.zip到本地,并解压得到includesrc文件夹,将include/*下的内容拷贝到/usr/local/include

glad.zip解压后的目录结构如下

-- glad
   | -- include
       | -- glad
       | -- KHR
   | -- src
       | -- glad.c
sudo mv include/* /usr/local/include
2.3 测试环境

创建一个目录code,并创建CMakeLists.txtman.cpp两个新文件,及一个build新文件夹

同时把前面glad目录下的src的glad/src/glad.c复制到code目录下,如下所示

-- code
   | -- build
   | -- CMakeLists.txt
   | -- man.cpp
   | -- glad.c

编辑main.cpp文件,如下所示:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
 
#include <iostream>
 
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
 
// 顶点着色器,GLSL语言
const char *vertexShaderSource = "#version 330 core\n" 
    "layout (location = 0) in vec3 aPos;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" 
    "}\0";
// 片元着色器
const char *fragmentShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n\0";
 
int main()
{
    // glfw: initialize and configure
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
 
    // glfw window creation
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
 
    // glad: load all OpenGL function pointers
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
 
 
    // build and compile our shader program
    // ------------------------------------
    // vertex shader
    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // 把这个着色器源码附加到着色器对象。着色器对象,源码字符串数量,VS真正的源码
    glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // fragment shader
    int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // check for shader compile errors
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // link shaders
    int shaderProgram = glCreateProgram(); // shaderProgram 是多个着色器合并之后并最终链接完成的版本
    glAttachShader(shaderProgram, vertexShader); // 附加
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    // check for linking errors
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
 
 
    float vertices[] = {
        -0.5f, -0.5f, 0.0f, // left  
         0.5f, -0.5f, 0.0f, // right 
         0.0f,  0.5f, 0.0f  // top   
    }; 
 
    unsigned int VBO, VAO;
	//创建VAO对象
    glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);
	//创建VBO对象,把顶点数组复制到一个顶点缓冲中,供OpenGL使用
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO); // 缓冲绑定到GL_ARRAY_BUFFER
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 顶点数据复制到缓冲的内存中
 
	//解释顶点数据方式
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // 顶点数据的解释
    glEnableVertexAttribArray(0);
 
    // 解绑VAO
	glBindVertexArray(0); 
	// 解绑VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
 
    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // input
        // -----
        processInput(window);
 
        // render
        // ------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
 
        // draw our first triangle
        glUseProgram(shaderProgram); // 激活shaderProgram,怎么画
        glBindVertexArray(VAO); // 画什么
        glDrawArrays(GL_TRIANGLES, 0, 3); // 开始画
 
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
 
    // optional: de-allocate all resources
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);
    glfwTerminate();
    
    return 0;
}
 
//键盘按键回调函数  
void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}
 
//调整窗口大小回调函数
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

CMakeLists.txt文件如下

make_minimum_required(VERSION 2.8)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
 
project(test)
 
find_package(glfw3 REQUIRED)
find_package( OpenGL REQUIRED )
include_directories( ${OPENGL_INCLUDE_DIRS} )
file(GLOB project_file glad.c main.cpp)
add_executable(${PROJECT_NAME} ${project_file})
 
target_link_libraries(${PROJECT_NAME}  ${OPENGL_LIBRARIES} glfw)

开始编译测试

cd build
cmake ..
make

执行完成后,在build文件下,生成了可执行文件text

运行该文件

./test

如下所示,成功!
在这里插入图片描述

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

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

相关文章

【数据结构】深度剖析栈的各接口功能实现

目录 &#x1f34a;前言&#x1f34a;&#xff1a; &#x1f95d;一.栈的概述&#x1f95d;&#xff1a; 1.栈的概念&#xff1a; 2.栈的结构&#xff1a; &#x1f349; 二、栈的各接口功能实现&#x1f349;&#xff1a; 1.栈的初始化&#xff1a; 2.压栈&#xff1a;…

十六进制转八进制(蓝桥杯基础练习C/C++)

我首先想到的就是十六进制转十进制&#xff0c;十进制转八进制&#xff0c;毕竟这样的方法是最常见的&#xff0c;但始终出现报错。 我想可能是int能储存的数范围太小了&#xff0c;就尝试用long long存储&#xff0c;结果还是报错。 #include <bits/stdc.h> using nam…

C++语法复习笔记-1. c++指针

文章目录1. 计算机内存1. 储存层次2. 内存单元与地址3. 指针定义2. 左值与右值1. 数组与指针1. 概念3. C中的原始指针1. 数组指针与指针数组2. const pointer 与 pointer to const3. 指向指针的指针4.关于野指针4.1 指向指针的指针4.2 NULL指针4.3 野指针5. 指针的基本运算5.1 …

Linux基础 IO

目录 一、文件操作 1.1 C语言文件操作 1.2 文件 系统调用接口 1.2.1 open/close函数 1.2.2 write/read函数 二、进程与文件 2.1 0&1&2 文件描述符 2.2 C语言FILE 2.3 (OS管理&进程找到) 被打开文件方法 2.3.1 struct file 描述文件属性(OS管理文件) 2.3…

线性时变系统的PID控制-2

在线性时变系统的PID控制-1的基础上采用S函数进行Simulink仿真。被控对象的描述方式可变换为&#xff1a;在S函数中&#xff0c;采用初始化、微分函数和输出函数&#xff0c;即mdllnitializeSizes函数、mdIDerivatives函数和mdlOutputs函数。在初始化中采用sizes结构&#xff0…

力扣sql简单篇练习(三)

力扣sql简单篇练习(三) 1 查找重复的电子邮箱 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT Email FROM Person GROUP BY Email HAVING count(id)>21.3 运行截图 2 每个产品在不同商店的价格 2.1 题目内容 2.1.1 基本题目信息 2.1.2 示…

[经典的图像warping方法] Thin Plate Spline: TPS理论和代码详解

0. 前言 2022年没有新写什么博客, 主要精力都在搞论文. 今年开始恢复! 本文的目标是详细分析一个经典的基于landmark(文章后面有时也称之为控制点control point)的图像warping(扭曲/变形)算法: Thin Plate Spine (TPS). TPS被广泛的应用于各类的任务中, 尤其是生物形态中应用…

动态内存管理(C语言)

目录 为什么要存在动态内存分配 动态内存函数的介绍 malloc函数 free函数 calloc函数 realloc函数 常见的动态内存错误 对NULL指针解引用错误 对动态开辟的空间越界访问 对非动态开辟内存使用free释放 使用free释放一块动态开辟内存的一部分 对同一块动态内存多次释放 动态开辟…

客快物流大数据项目(一百零五):启动ElasticSearch

文章目录 启动ElasticSearch 一、启动ES服务端 二、​​​​​​​启动Kibana 启动ElasticSearch

【NI Multisim 14.0虚拟仪器设计——放置虚拟仪器仪表(频率计数器)】

目录 序言 &#x1f3ee;放置虚拟仪器仪表&#x1f3ee; &#x1f9e7;频率计数器&#x1f9e7; &#x1f973;&#x1f973;&#xff08;1&#xff09;“测量”选项组:参数测量区。 &#x1f973;&#x1f973;&#xff08;2&#xff09;“耦合”选项组:用于选择电流耦合方…

CSDN 的故障处理流程,实例分享

CSDN 的研发团队每隔一段时间会和大家分享团队的进展&#xff0c;请看&#xff1a; 2021 年年底的汇报 2022 年上半年的汇报 2022 年下半年的汇报 从上面的报告中大家可以看到&#xff0c;我们在取得进展的同时&#xff0c; 也碰到了很多问题&#xff0c;也有一些困惑。 我写了…

「链表」简析

前言 前言&#xff1a;研究一个数据结构的时候&#xff0c;首先讲的是增删改查。 文章目录前言一、链表简介1. 含义2. 节点组成3. 存储方式1&#xff09;数据在内存中的存储方式2&#xff09;单链表在内存中的存储方式3&#xff09;双链表在内存中的存储方式4&#xff09;循环链…

ZYNQ IP核之MMCM/PLL

锁相环&#xff08;Phase Locked Loop&#xff0c;PLL&#xff09;&#xff0c;一种反馈控制电路&#xff0c;对时钟网络进行系统级的时钟管理和偏移控制&#xff0c;具有时钟倍频、分频、相位偏移和可编程占空比的功能。 Xilinx 7系列器件中的时钟资源包含了时钟管理单元CMT&…

SAPIEN PrimalSQL 2023.1[x64] Crack

SAPIEN PrimalSQL 2023.1 使数据库查询开发和测试变得轻而易举&#xff0c;无论您的数据库类型或供应商如何。 通过单个工具支持多个数据库提供程序。 Access、SQL Server、SQL Server Compact、MySQL、Oracle、ODBC、OLEDB、Sybase 等。 使用Visual Query Builder构建复杂的…

maven基础

一、Maven基础 为什么要学习Maven&#xff1f; Maven作为依赖管理工具&#xff0c;能够管理大规模的jarjarjar包&#xff0c;使用MavenMavenMaven后&#xff0c;依赖对应的JarJarJar包&#xff0c;能够自动下载、方便、快捷切规范。Maven作为构建管理工具&#xff0c;当我们使…

HTTP实用指南

HTTP实用指南 01.初始HTTP 当我们在浏览器地址栏输入一个网址或者关键字&#xff0c;它会给我们跳转到对应的网页&#xff0c;在这一过程中&#xff0c;内部到底是怎么运作的&#xff1f; 总结上述图片过程&#xff0c;用流程图来表示&#xff0c;如下&#xff1a; 处理输入信…

【论文翻译】Semantic Graph Convolutional Networks for 3D Human Pose Regression

【iccv论文】https://openaccess.thecvf.com/content_CVPR_2019/papers/Zhao_Semantic_Graph_Convolutional_Networks_for_3D_Human_Pose_Regression_CVPR_2019_paper.pdf 【github】https://github.com/garyzhao/SemGCN 摘要 在本文中&#xff0c;我们研究了用于回归的图卷积网…

ANR触发机制分析

ANR是一套监控Android应用程序响应是否及时的机制&#xff0c;可以把发生ANR比作是引爆炸弹&#xff0c;那么整个流程包含三部分组成&#xff1a; 埋定时炸弹&#xff1a;system_server进程启动倒计时&#xff0c;在规定时间内如果目标应用进程没有干完所有的活&#xff0c;则…

QEMU之一调试uboot(vexpress-a9)

u-boot版本&#xff1a;u-boot-2017.05开发板&#xff1a;vexpress-a9&#xff08;没办法&#xff0c;目前看到的都是这个开发板&#xff0c;想QEMU调试tiny210,一直没看到怎么修改qemu&#xff09;编译u-boot&#xff1a;make ARCHarm CROSS_COMPILEarm-linux-gnueabi- vexpre…

Avast 发布免费的 BianLian 勒索软件解密器

安全软件公司 Avast 发布了 BianLian 勒索软件的免费解密器&#xff0c;以帮助恶意软件的受害者在不向黑客支付费用的情况下恢复锁定的文件。 在 2022 年夏天 BianLian 勒索软件的活动增加后大约半年&#xff0c;该威胁组织入侵了多个知名组织&#xff0c;解密器的可用性就出现…