【小沐学OpenGL】Ubuntu环境下glad的安装和使用

ops/2024/10/21 6:05:49/

文章目录

  • 1、简介
    • 1.1 OpenGL简介
    • 1.2 glad简介
  • 2、安装glad
    • 2.1 手动安装glad
    • 2.2 git安装glad
    • 2.3 源码编译成glad单独库
  • 3、测试glad
    • 3.1 例子1
    • 3.2 例子2
  • 结语

1、简介

1.1 OpenGL简介

OpenGL作为图形界的工业标准,其仅仅定义了一组2D和3D图形接口API,而对于窗口管理、IO消息响应等并没有规定。也就是说,OpenGL依赖各平台提供用于渲染的context以及具体实现方式,而各平台提供的实现不尽相同。这些实现主要有:Windows平台下的WGL、Linux下的Mesa/GLX、Mac OS X下的Cocoa/NSGL,以及跨平台的GLUT、GLFW、SDL等等。

Mesa是Linux下的OpenGL实现。它提供了对AMD Radeon系列、Nvidia GPU、Intel i965, i945, i915以及VMWare虚拟GPU等多种硬件驱动的支持,同时也提供了对softpipe等多种软件驱动的支持。Mesa项目由Brian Paul于1993年8月创建,于1995年2月发布了第一个发行版,此后便受到越来越多的关注,如今Mesa已经是任何一个Linux版本首选的OpenGL实现。

GLX则是在Linux上用于提供GL与窗口交互、窗口管理等等的一组API。它的作用与Windows的WGL、Mac OS X的AGL以及针对OpenGL ES的EGL相似。在Linux上,窗口创建、管理等API遵循X Window接口,而GLX提供了OpenGL与X Window交互的办法。因此GLX也可以运用于其他使用X Window的平台,例如FreeBSD等。

在Debian/Ubuntu系统上,使用以下命令来安装Mesa和GLX:

sudo apt-get install libgl1-mesa-dev

安装OpenGL ES版本的Mesa:

sudo apt-get install libgles2-mesa-dev

对于OpenGL ES,EGL的安装如下:

sudo apt-get install libegl1-mesa-dev

查看安装的Mesa版本以及安装是否成功:

glxinfo | grep "OpenGL version"

在这里插入图片描述

1.2 glad简介

Windows平台由于微软的Direct3D存在,微软对OpenGL的支持并不积极。在大多数微软操作系统中所支持OpenGL版本还是1.0和1.1,仅支持固定管线API,对于现代使用OpenGL开发的程序并不友好。不过通过OpenGL的ARB扩展机制可以让我们访问到OpenGL的高级特性接口。

GLAD 是一个用于加载 OpenGL 函数指针的库,它简化了 OpenGL 函数的调用。你可以从 GLAD 的官方网站下载并生成适合你需求的 GLAD 配置。通常,你需要指定 OpenGL 的版本和配置文件类型(通常是核心模式)。生成后,将包含的头文件和源文件添加到你的项目中。

GLAD使用步骤:GLAD可以使OpenGL基础渲染变得简单,流程如下:

  • 1.初始化GLAD库,加载所有OpenGL函数指针。
  • 2.创建着色器并附加到着色器程序。
  • 3.构建缓冲对象并附加到顶点属性。
  • 4.使用着色器程序,利用渲染接口将缓冲对象按照指定图元类型渲染出来。

初始化GLAD库:常用接口如下:

  • int gladLoadGLLoader(GLADloadproc load):任何的OpenGL接口调用都必须在初始化GLAD库后才可以正常访问。如果成功的话,该接口将返回GL_TRUE,否则就会返回GL_FALSE。
  • 其中GLADloadproc函数声明如下:
    void* (GLADloadproc)(const char name)

2、安装glad

2.1 手动安装glad

配置GLAD需要设置OpenGL版本,可以通过glxinfo查看;

# 安装glxinfo
sudo apt install mesa-utils# 查看OpenGL版本
glxinfo | grep "OpenGL version"

在这里插入图片描述
可以看到笔者的是3.1。

https://glad.dav1d.de/

在这里插入图片描述
下载glad源码如下:
在这里插入图片描述
在这里插入图片描述
通过CMake构建项目,其CMakeLists.txt添加如下代码:

add_library(glad glad/src/glad.c)
target_include_directories(glad  PUBLIC glad/include)
target_link_libraries(main glfw ${GL_LIBRARY} glad)

解压glad.zip如下:
在这里插入图片描述

  • 方法1:
cd glad/include
sudo mv glad/ /usr/local/include #将glad目录移动到/usr/local/include
sudo mv KHR/ /usr/local/include #将KHR目录移动到/usr/local/include

最后将glad/src目录下的glad.c文件拷贝一份到你的工程源码目录下,如跟main.cpp文件在同一个目录下。

  • 方法2:
    或者点击GENERRATE生成对应的zip文件并下载。解压这个zip文件,可以一个包含include和src的文件夹,将include下的文件移动到系统目录下:
sudo mv include/* /usr/local/include

src目录下的glad.c文件稍后放置在工程文件中。

mv <glad_path>/src/glad.c glad.c

2.2 git安装glad

git clone https://github.com/Dav1dde/glad.git
cd glad
cmake ./
make
sudo cp -a include /usr/local/

2.3 源码编译成glad单独库

  • (1)下载glad的include, src 到 3rdparty/glad/
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • (2)在 3rdparty/glad/里新建CMakeLists.txt文件如下:
cmake_minimum_required(VERSION 3.0)
project(Glad)add_library(glad include/glad/glad.h src/glad.c)
target_include_directories(glad PUBLIC include/)
  • (3)在项目主 CMakeLists.txt 加入下面的代码.
cmake_minimum_required(VERSION 2.8.1)project(my_app)find_package(glfw3 REQUIRED)
add_subdirectory(3rdparty/glad)add_executable(my_app main.cpp)
target_link_libraries(my_app glfw glad)

在这里插入图片描述

3、测试glad

3.1 例子1

新建CMakeLists.txt内容如下:

  • CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.1)project(my_project)find_package(OpenGL REQUIRED)
add_library(glad src/glad.c)
target_include_directories(glad  PUBLIC include/glad)set (CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -ldl")add_executable(main main.cpp)
target_link_libraries(main glfw ${GL_LIBRARY} glad)
  • main.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height);
}int main()
{glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);GLFWwindow* window = glfwCreateWindow(800, 600, "Linux Opengl, yxy", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}glViewport(0, 0, 800, 600);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);while(!glfwWindowShouldClose(window)){glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glfwSwapBuffers(window);glfwPollEvents();}glfwTerminate();return 0;
}

编译如下:
在这里插入图片描述

3.2 例子2

  • CMakeLists.txt:

CMakeLists.txt文件内容同上。

  • 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);// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;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); // uncomment this statement to fix compilation on OS X
#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 shaderint vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// check for shader compile errorsint 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 shaderint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);// check for shader compile errorsglGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success){glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;}// link shadersint shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);// check for linking errorsglGetProgramiv(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);// set up vertex data (and buffer(s)) and configure vertex attributes// ------------------------------------------------------------------float vertices[] = {0.5f,  0.5f, 0.0f,  // top right0.5f, -0.5f, 0.0f,  // bottom right-0.5f, -0.5f, 0.0f,  // bottom left-0.5f,  0.5f, 0.0f   // top left};unsigned int indices[] = {  // note that we start from 0!0, 1, 3,  // first Triangle1, 2, 3   // second Triangle};unsigned int VBO, VAO, EBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbindglBindBuffer(GL_ARRAY_BUFFER, 0);// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.glBindVertexArray(0);// uncomment this call to draw in wireframe polygons.//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);// 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 triangleglUseProgram(shaderProgram);glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized//glDrawArrays(GL_TRIANGLES, 0, 6);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);// glBindVertexArray(0); // no need to unbind it every time// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)// -------------------------------------------------------------------------------glfwSwapBuffers(window);glfwPollEvents();}// optional: de-allocate all resources once they've outlived their purpose:// ------------------------------------------------------------------------glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);// glfw: terminate, clearing all previously allocated GLFW resources.// ------------------------------------------------------------------glfwTerminate();return 0;
}// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true);
}// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{// make sure the viewport matches the new window dimensions; note that width and// height will be significantly larger than specified on retina displays.glViewport(0, 0, width, height);
}

在这里插入图片描述

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!


http://www.ppmy.cn/ops/109786.html

相关文章

最大熵模型(Maximum Entropy Model)—有监督学习方法、概率模型、生成模型、线性模型、参数化模型、批量学习

定义 假设满足所有约束条件的模型集合为&#xff1a; C { P ∈ P ∣ E p ( f i ) E p ~ ( f i ) , i 1 , 2 , ⋯ , n } {\tt C}\left\{ P \in {\tt P} | E_p(f_i)E_{\tilde{p}(f_i)},i1,2,\cdots,n\right\} C{P∈P∣Ep​(fi​)Ep~​(fi​)​,i1,2,⋯,n} E p ( f ) ∑ x ,…

基于SpringBoot的点餐平台网站

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架&#xff0c;Java技术 工具&#xff1a;IDEA/Eclipse、Navicat、Maven、Tomcat 系统…

存储课程学习笔记8_spdk的安装以及简单demo测试

已经对相关的基础概念有一定的了解&#xff0c;比如裸盘&#xff0c;文件系统&#xff0c;读写相关裸盘&#xff0c;裸盘挂载使用&#xff0c;内核插入文件系统的方式&#xff0c;相关操作io的库或者函数&#xff08;io_uring, readv&#xff0c;writev, mmap等&#xff09;&am…

MFC工控项目实例之十四模拟量信号名称从文件读写

承接专栏《MFC工控项目实例之十三从文件读写板卡信号名称》 在BoardTest.cpp文件中添加代码 int m_CountGetCurSel_AD[16];//索引号 UINT m_CountComboID_AD[16]//控件ID号{IDC_COMBO33,IDC_COMBO34,IDC_COMBO35,IDC_COMBO36,IDC_COMBO37,IDC_COMBO38,IDC_COMBO39,IDC_COMBO40…

springboot体会BIO(阻塞式IO)

使用springboot体会阻塞式IO 大致的思路为&#xff1a; 创建一个socket服务端&#xff0c;监听socket通道&#xff0c;并打印出socket通道中的内容。 创建两个socket客户端&#xff0c;向socket服务端写入消息。 1.创建服务端 public class RedisServer {public static void m…

基于YOLOv10的光伏板缺陷检测系统

基于YOLOv10的光伏板缺陷检测系统 (价格90) 包含 [鸟落, 干净, 破裂, 灰尘] 4个类 通过PYQT构建UI界面&#xff0c;包含图片检测&#xff0c;视频检测&#xff0c;摄像头实时检测。 &#xff08;该系统可以根据数据训练出的yolov10的权重文件&#xff0c;运用在其…

Redis、memcache、MongoDB 对比

1. 数据结构和存储方式 Redis Redis 是一个开源的内存数据库&#xff0c;支持丰富的数据结构。它的数据类型包括&#xff1a; 字符串&#xff08;String&#xff09;哈希&#xff08;Hash&#xff09;列表&#xff08;List&#xff09;集合&#xff08;Set&#xff09;有序集…

设计模式之装饰器模式:让对象功能扩展更优雅的艺术

一、什么是装饰器模式 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff08;Structural Pattern&#xff09;&#xff0c;它允许用户通过一种灵活的方式来动态地给一个对象添加一些额外的职责。就增加功能来说&#xff0c;装饰器模式相比使用…