前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenGL及其相关开源库:深入探析图形编程工具与原理

OpenGL及其相关开源库:深入探析图形编程工具与原理

作者头像
点云PCL博主
发布2024-05-11 16:33:47
2650
发布2024-05-11 16:33:47
举报
文章被收录于专栏:点云PCL点云PCL

在现代计算机图形学中,OpenGL及其相关的开源库扮演着至关重要的角色。这些库提供了丰富的功能和工具,使得开发者可以轻松地创建复杂的图形应用程序。这里总结的探讨一下OpenGL、GLEW、GLFW、GLM、Assimp以及GL、GLUT、FreeGLUT、GLAD等库之间的联系和概念,以及它们在图形编程中的作用。

OpenGL及其基础概念

OpenGL(Open Graphics Library)是一种跨平台的图形API,用于渲染2D和3D图形。它提供了一组用于渲染图形的函数,允许开发人员利用GPU的强大性能来创建复杂的图形效果。OpenGL是一个开放标准,由Khronos Group维护和更新。OpenGL只有框架没有实现,因为OpenGL只有函数声明没有源文件实现,类似于接口和虚函数,所有的实现是显卡生产商提供。比如NVIDIA或者AMD就要自己实现OpenGL函数内容,所以不同的生产商可以对自己的产品提供优化。OpenGL函数库相关的API有核心库(gl),实用库(glu),辅助库(aux)、实用工具库(glut),窗口库(glx、agl、wgl)和扩展函数库等。gl是核心,glu是对gl的部分封装,glx、agl、wgl 是针对不同窗口系统的函数。glut是为跨平台的OpenGL程序的工具包,扩展函数库是硬件厂商为实现硬件更新利用OpenGL的扩展机制开发的函数。

GLEW(OpenGL Extension Wrangler Library):是一个专门用于管理OpenGL扩展的C/C++库。在图形编程中,随着时间的推移,OpenGL的功能不断扩展和更新,新的特性和功能以扩展的形式添加到OpenGL中。这些扩展提供了额外的功能,如新的渲染技术、更高效的渲染管线、新的图形效果等。然而,不同的OpenGL实现可能支持不同的扩展,而且开发者需要编写不同的代码来适配不同的扩展,这会增加开发的复杂性。这就是GLEW发挥作用的地方。GLEW简化了使用OpenGL扩展的过程。它提供了一组函数来查询和加载OpenGL的扩展,使得开发者可以轻松地使用最新的功能而不必担心不同平台之间的差异。具体来说,GLEW提供了以下功能:

  1. 扩展查询:GLEW允许开发者查询当前OpenGL实现所支持的所有扩展。通过调用相应的函数,开发者可以获取有关支持的扩展的信息,如名称、版本、是否可用等。
  2. 扩展加载:GLEW还提供了加载OpenGL扩展函数指针的功能。开发者只需在初始化OpenGL上下文后调用GLEW的初始化函数,它将自动检测和加载所需的扩展函数,使得开发者可以直接使用这些函数而无需手动加载。
  3. 跨平台兼容性:由于不同的操作系统和图形驱动程序可能有不同的OpenGL实现,因此编写跨平台的OpenGL代码可能会面临一些挑战。GLEW通过提供统一的接口来解决这个问题,使得开发者可以编写一次代码,在不同的平台上都能正常工作。

总的来说,GLEW简化了使用OpenGL扩展的过程,提高了开发效率,同时保证了跨平台的兼容性。开发者可以更加专注于实现图形应用的功能和效果,而无需过多关注底层的扩展加载和管理细节。

GLFW(Graphics Library Framework):的设计目的是为了简化图形应用程序的开发过程,特别是在涉及窗口创建和用户输入处理方面。操作系统的窗口系统通常是复杂且具有差异的,因此直接与之交互会增加开发者的工作量。GLFW通过提供一个统一的接口,为开发者屏蔽了底层操作系统的差异,使得开发图形应用程序变得更加简单和高效,GLFW库提供了以下支持:

  1. 跨平台支持:GLFW是跨平台的,支持Windows、macOS和Linux等操作系统。这意味着开发者可以编写一次代码,在不同的操作系统上都能够运行,而无需对每个平台进行特定的适配和调整。
  2. 简单易用的API:GLFW的API设计简单而直观,使得开发者可以轻松地创建窗口、处理用户输入等操作。例如,只需几行代码就可以创建一个窗口,并且可以轻松地设置窗口大小、标题等属性。
  3. 窗口管理:GLFW提供了一套功能强大的窗口管理功能,包括窗口的创建、关闭、最小化、最大化等操作。开发者可以通过简单的API调用来管理窗口的状态。
  4. 事件处理:GLFW能够处理各种事件,包括键盘事件、鼠标事件、窗口事件等。开发者可以注册回调函数来处理这些事件,从而实现与用户的交互。
  5. 多窗口支持:GLFW支持创建多个窗口,每个窗口可以拥有自己的上下文和事件处理逻辑。这使得开发者可以实现复杂的图形界面,如多窗口应用程序或者游戏引擎。
  6. 轻量级和高效性:GLFW是一个轻量级的库,具有很高的性能。它采用了优化的实现方式,使得窗口的创建和事件处理等操作能够以高效的方式进行。

所以GLFW是一个功能强大、简单易用且跨平台的图形库,它为开发者提供了一个统一的接口来创建和管理窗口,并处理用户输入,使得图形应用程序的开发变得更加简单和高效。

GLM(OpenGL Mathematics):是一个专门针对OpenGL和图形学的数学库,旨在提供各种数学函数和数据结构,以便于在图形编程中进行数学计算。GLM的设计目标是与OpenGL API兼容,并且提供了类似于GLSL(OpenGL Shading Language)的语法和功能,使得在CPU上进行与GPU相似的数学运算成为可能。GLM库提供以下支持:

  1. 向量和矩阵操作:GLM提供了丰富的向量和矩阵操作函数,包括向量和矩阵的加减乘除、点积、叉积、转置、逆矩阵等。这些操作是图形编程中经常使用的基本数学运算,如顶点变换、矩阵变换等。
  2. 四元数:GLM还提供了四元数的支持,包括四元数的加减乘除、共轭、归一化、插值等操作。四元数在图形学中广泛应用于旋转表示,如相机的旋转、物体的旋转等。
  3. GLSL风格的语法:GLM的语法和功能与GLSL非常相似,包括向量和矩阵的构造函数、成员访问、运算符重载等。这使得开发者可以轻松地将GLM与GLSL结合使用,实现CPU和GPU之间的无缝数据传输和计算。
  4. 兼容性和可移植性:GLM是一个纯头文件库,不依赖于任何第三方库,因此非常容易集成到现有的项目中。它还提供了丰富的文档和示例,使得开发者可以快速上手并充分利用其功能。
  5. 性能优化:GLM采用了优化的实现方式,使得在CPU上进行数学运算时能够获得良好的性能表现。它利用了现代CPU的SIMD指令集和多核处理器的并行计算能力,以实现高效的数学运算。

所以GLM是一个功能丰富、易于使用且高性能的数学库,为图形编程提供了强大的数学支持。通过与OpenGL API的兼容性和GLSL风格的语法,GLM使得开发者可以轻松地在CPU上进行与GPU相似的数学运算,从而实现复杂的图形效果和计算。

Assimp(Open Asset Import Library):是一个功能强大的库,专门用于导入和导出各种不同格式的3D模型文件。在图形编程中,经常需要处理来自不同来源和不同格式的3D模型,比如OBJ、FBX、Collada等。而Assimp的作用就是为开发者提供一个统一的接口,使得他们可以轻松地导入这些不同格式的模型文件,并且能够方便地在程序中进行处理和使用。Assimp库提供以下支持:

  1. 支持多种文件格式:Assimp支持导入和导出多种常见的3D模型文件格式,包括但不限于OBJ、FBX、Collada、STL、3DS等。这意味着开发者可以直接使用Assimp来处理各种来源的模型文件,而不必依赖于不同的导入工具或者库。
  2. 统一的数据结构:Assimp将不同格式的模型文件转换为统一的数据结构,使得开发者可以以统一的方式访问模型的顶点、法线、纹理坐标等信息。这样一来,开发者可以编写通用的代码来处理不同格式的模型,而不必针对每种格式编写特定的逻辑。
  3. 额外的功能:除了基本的模型导入和导出功能之外,Assimp还提供了一些额外的功能,如网格处理、纹理加载、材质处理等。开发者可以利用这些功能来进一步处理模型,比如进行网格优化、纹理映射、材质转换等操作。
  4. 跨平台兼容性:Assimp是一个跨平台的库,支持Windows、macOS、Linux等操作系统。这意味着开发者可以在不同的平台上使用相同的代码来处理模型文件,而不必担心平台之间的差异性。
  5. 活跃的社区支持:Assimp拥有一个活跃的开发者社区,提供了丰富的文档、示例代码和技术支持。开发者可以通过社区论坛、邮件列表等渠道获取帮助,解决在使用Assimp过程中遇到的问题。

所以Assimp是一个非常实用和强大的库,为开发者处理各种不同格式的3D模型提供了便利和支持。它的统一接口、多种文件格式支持以及额外的功能使得开发者能够更加轻松地导入、处理和使用3D模型文件,从而加速开发过程并提高效率。

GL、GLUT、FreeGLUT和GLAD

GL(Graphics Library):GL是OpenGL的前身,是图形编程中的基础库之一。它提供了一系列基本的图形函数,如绘制点、线、三角形等。在早期的OpenGL版本中,开发者通常会直接使用GL库来进行基本的图形绘制,例如通过调用glBegin()和glEnd()来指定绘制的几何形状,并使用glVertex()来指定顶点坐标。尽管现代OpenGL已经淘汰了这些固定管线的绘制方式,转而采用可编程着色器的方式,但GL仍然作为OpenGL的一部分存在,并且在一些特定的场景下仍然会被使用到。

GLUT(OpenGL Utility Toolkit):GLUT是一个用于创建窗口和处理用户输入的库,旨在简化OpenGL应用程序的开发过程。它提供了一组简单易用的函数,如创建窗口、处理键盘和鼠标输入、管理窗口事件等。通过使用GLUT,开发者可以快速地搭建起一个基本的OpenGL应用程序框架,而无需关注底层的窗口管理和事件处理细节。然而,由于GLUT的功能相对有限,缺乏灵活性,因此在一些复杂的应用场景下可能会显得力不从心。

FreeGLUT:FreeGLUT是GLUT的开源替代品,旨在改进和扩展GLUT的功能,并且保持了兼容性。相比于GLUT,FreeGLUT在功能上进行了一些改进和扩展,如支持多窗口、支持更多的键盘和鼠标事件、提供了更多的定时器函数等。同时,FreeGLUT也修复了一些GLUT中存在的bug和不足之处,使得开发者可以更加灵活地使用和扩展这个库。

GLAD(OpenGL Loader Generator):GLAD是一个用于加载OpenGL函数指针的库,旨在简化跨平台的OpenGL开发过程。在使用OpenGL时,通常需要加载OpenGL的函数指针,以便在运行时调用OpenGL的函数。而GLAD的作用就是自动生成这些函数指针的加载代码,从而使得开发者可以轻松地在不同的平台上使用OpenGL,并且不必担心手动加载函数指针的问题。GLAD可以根据用户指定的OpenGL版本和扩展列表自动生成相应的加载代码,并且支持多种编程语言,如C/C++、Python等,使得开发者可以在不同的开发环境中使用。

这些库之间存在着密切的联系,它们通常一起使用以实现复杂的图形应用程序。例如,一个典型的OpenGL应用可能会使用GLEW来管理OpenGL的扩展,GLFW来创建窗口和处理用户输入,GLM来进行数学计算,以及Assimp来加载和处理3D模型。而在早期的OpenGL开发中,开发者可能会使用GLUT或者FreeGLUT来创建窗口和处理输入。

代码实现

代码1

代码语言:javascript
复制
// 包含标准头文件
#include <stdio.h>
#include <stdlib.h>
// 包含 GLEW 库
#include <GL/glew.h>
// 包含 GLFW 库
#include <GLFW/glfw3.h>
// 包含 GLM 库
#include <glm/glm.hpp>
using namespace glm;
GLFWwindow* window;

int main(void)
{
        // 初始化 GLFW
        if (!glfwInit())
        {
               fprintf(stderr, "Failed to initialize GLFW\n");
               getchar();
               return -1;
        }
        glfwWindowHint(GLFW_SAMPLES, 4); // 设置多重采样抗锯齿
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // OpenGL 主版本号
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // OpenGL 次版本号
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 让 macOS 平台兼容性更好,通常不需要
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用核心模式
        // 创建窗口及其 OpenGL 上下文
        window = glfwCreateWindow(1024, 768, "hello world 01", NULL, NULL);
        if (window == NULL) {
               fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they  are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
               getchar();
               glfwTerminate();
               return -1;
        }
        glfwMakeContextCurrent(window);
        // 初始化 GLEW
        if (glewInit() != GLEW_OK) {
               fprintf(stderr, "Failed to initialize GLEW\n");
               getchar();
               glfwTerminate();
               return -1;
        }
        // 确保能够捕获 ESC 键被按下事件
        glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
        // 设置暗蓝色背景
        glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
        do {
               // 清空屏幕。
               glClear(GL_COLOR_BUFFER_BIT);
               // 什么也不绘制
               // 交换缓冲区
               glfwSwapBuffers(window);
               glfwPollEvents();
        } // 检查 ESC 键是否被按下或窗口是否被关闭
        while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
               glfwWindowShouldClose(window) == 0);
        // 关闭 OpenGL 窗口并终止 GLFW
        glfwTerminate();
        return 0;
}

运行结果

代码2

代码语言:javascript
复制
#include <GL/glut.h>
#include <cmath> // 包含cmath头文件
#include <iostream>

float cameraAngleX = 45.0f; // 相机的X轴旋转角度
float cameraAngleY = 45.0f; // 相机的Y轴旋转角度
float cameraDistance = 10.0f; // 相机与原点的距离

int lastMouseX = 0; // 上一次鼠标X位置
int lastMouseY = 0; // 上一次鼠标Y位置

void init() {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 设置背景色为黑色
    glEnable(GL_DEPTH_TEST); // 启用深度测试
}

void drawGrid() {
    // 绘制网格线
    glColor3f(1.0f, 1.0f, 1.0f); // 设置颜色为白色
    glBegin(GL_LINES);
    // 绘制水平线
    for (float i = -10.0f; i <= 10.0f; ++i) {
        glVertex3f(-10.0f, 0.0f, i);
        glVertex3f(10.0f, 0.0f, i);
    }
    // 绘制垂直线
    for (float i = -10.0f; i <= 10.0f; ++i) {
        glVertex3f(i, 0.0f, -10.0f);
        glVertex3f(i, 0.0f, 10.0f);
    }

    glEnd();
}

void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    // 设置相机位置和视角
    gluLookAt(cameraDistance * sin(cameraAngleX * 3.14159265f / 180.0f), cameraDistance * sin(cameraAngleY * 3.14159265f / 180.0f), cameraDistance * cos(cameraAngleX * 3.14159265f / 180.0f),
              0.0f, 0.0f, 0.0f,
              0.0f, 1.0f, 0.0f);
    drawGrid();
    glutSwapBuffers();
}


void reshape(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (GLfloat)w / (GLfloat)h, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void mouse(int button, int state, int x, int y) {
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        lastMouseX = x;
        lastMouseY = y;
    }
}


void motion(int x, int y) {
    float deltaX = x - lastMouseX;
    float deltaY = y - lastMouseY;

    cameraAngleX += deltaX * 0.1f;
    cameraAngleY += deltaY * 0.1f;

    lastMouseX = x;
    lastMouseY = y;

    glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y) {
    switch (key) {
        case 27: // ESC键
            exit(0);
            break;
        case '+': // 放大视角
            cameraDistance -= 0.1f;
            if (cameraDistance < 1.0f) cameraDistance = 1.0f;
            break;
        case '-': // 缩小视角
            cameraDistance += 0.1f;
            if (cameraDistance > 20.0f) cameraDistance = 20.0f;
            break;
    }
    glutPostRedisplay();
}


int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("OpenGL Window");

    init();

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);

    glutMainLoop();
    return 0;
}

运行结果

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-05-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 点云PCL 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
GPU 云服务器
GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档