自学内容网 自学内容网

6、OpenGL-glad 函数加载

1. OpenGL函数加载

  • OpenGL是一个规范标准,不是具体的实现
  • 实现靠各家显卡厂商编写的驱动程序
  • 程序如果需要运行,需要向显卡驱动查询函数的具体位置并且加载进来

2. glad 加载函数

注: OpenGL是一个规范标准,而不是具体的实现,是由各家显卡厂商编写的驱动程序实现的, 所以程序如果需要运行,就需要向显卡驱动查询函数的具体位置并且加载进来。

// 加载OpenGL的函数指针  
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {  
        // 处理错误
        return -1;  
    }  

GLADloadproc

  • GLADloadproc 是一个在 GLAD 中定义的函数指针类型。它是指向一个函数的指针,这个函数不接受任何参数,并返回一个指向 OpenGL 的函数,如 glClear、glGenBuffers 等

glfwGetProcAddress

  • glfwGetProcAddress 是 GLFW 库中的一个函数,用于检索 OpenGL 或 OpenGL ES 函数地址。当有一个 OpenGL 上下文时(通过 GLFW 创建的),可以使用这个函数来获取特定 OpenGL 函数的地址。这个地址被用作一个函数指针来调用相应的 OpenGL 函数

工作原理

  • 当使用 GLAD 来加载 OpenGL 函数时,需要提供一个“加载函数”,这个函数能够返回 OpenGL 函数的地址。GLAD 提供了 gladLoadGLLoader 函数,它接受一个符合 GLADloadproc 类型的函数指针作为参数。可以将 glfwGetProcAddress 转换为 GLADloadproc 类型,并将其作为参数传递给 gladLoadGLLoader。
  • 当 gladLoadGLLoader 被调用时,它会遍历一个内部列表,该列表包含了它想要加载的所有 OpenGL 函数的名称。对于列表中的每个函数,它都会调用提供的加载函数,传入函数的名称,并接收该函数的地址。然后,它会将这些地址存储在内部结构中,以便稍后可以通过 GLAD 提供的宏或函数指针来调用这些 OpenGL 函数。
  • 如果 glfwGetProcAddress 无法找到某个函数的地址通常不会发生,除非OpenGL 上下文不支持该函数,或者驱动程序有问题),gladLoadGLLoader 可能会记录一个错误(取决于它的实现),但通常会继续尝试加载其他函数。如果它无法加载任何函数,或者遇到了其他严重错误,它将返回 false,此时应该进行错误处理。然而,在正常情况下,如果你已经成功创建了 OpenGL 上下文,并且你的驱动程序是最新的,那么 gladLoadGLLoader 应该能够成功加载所有必要的 OpenGL 函数。

glad 作用综述

  • 主要作用是简化OpenGL函数指针的加载过程。由于OpenGL的驱动版本众多,且不同版本的OpenGL函数可能位于不同的位置,因此在编译时无法确定所有函数的具体地址。这就需要在运行时查询并加载这些函数指针。

GLAD的作用可以归纳为以下几点:

  • 自动化加载OpenGL函数指针:GLAD能够自动加载当前OpenGL上下文支持的所有函数指针,并将它们存储在易于访问的位置。这样,开发者就可以直接使用这些函数指针来调用OpenGL函数,而无需手动查询和加载它们。
  • 简化OpenGL编程:通过使用GLAD,开发者可以更加专注于OpenGL的图形渲染逻辑,而无需担心函数指针的加载问题。这大大简化了OpenGL编程的复杂性。
  • 提高兼容性:由于GLAD能够加载不同版本的OpenGL函数指针,因此它可以提高OpenGL应用程序的兼容性。开发者可以编写一次代码,并在不同的OpenGL版本上运行,而无需对函数指针的加载进行特殊处理。

3. 状态机

  • OpenGL运行环境是一个大的状态机,每一个函数都会改变状态机的状态或者触发其执行某个行为。
  • OpenGL状态机(OpenGL State Machine)是OpenGL图形库中的一个核心概念,用于管理和控制图形渲染的状态。它是一种基于状态的编程模型,通过设置不同的状态来定义和控制OpenGL的行为。

4. OpenGL基础函数

4.1 设置视口

glViewport(GLintx,GLinty,GLsizeiwidth,GLsizeiheight);
//设置窗口中opengl负责渲染的区域,即视口(Viewport)
// x,y:表示相对窗口左下角的起始位置
//width,height:表示渲染区域的长度、高度

4.2 设置画布清理颜色

glClearColor(GLfloatred,GLfloatgreen,GLfloatblue,GLfloatalpha);// rgba  颜色值 0-1

4.3 执行画布清理

glCIear(GL_COLOR_BUFFER_BIT)

4.4 双缓冲

双缓冲技术,在每一帧绘制任务完成后,需要把“背后”的画布放到台前,把台前的撤到“背后"

voidglfwSwapBuffers(GLFWwindow*window);

main.c

#include <glad/glad.h>  // glad 头文件需要在glfw前引入
#include <GLFW/glfw3.h>  
#include <stdio.h>

/**
 * 声明响应窗体大小变化的函数
*/
void frameBufferSizeCallBack(GLFWwindow* window, int width, int height) {
    printf("窗体变化后大小:%d, %d\n", width, height);
}

/**
 * 键盘消息回调函数
 * 参数:
 *      key:字母按键码
 *      scancode:物理按键码
 *      action:按下还是抬起
 *      mods:是否有shift或ctrl
*/
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
        if (key == GLFW_KEY_W) {
            //触发了w
        }
        if (action == GLFW_PRESS) {
            //键位按下
        }
        if (action == GLFW_RELEASE) {
            //键位抬起
        }
        if (mods == GLFW_MOD_CONTROL) {
            //按下ctrl的同时,按下了key
        }
        if (mods == GLFW_MOD_SHIFT) {
            //按下shift的同时,按下了key
        }
        printf("按下按键:%c\n", key); 

}

int main(void) {  
    GLFWwindow* window;  

    if (!glfwInit())  
        return -1;  

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); //主版本号
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);//次版本号
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//使用核心模式

    window = glfwCreateWindow(800, 600, "Hello World", NULL, NULL);  
    if (!window) {  
        glfwTerminate();  
        printf("create window faild\n"); 
        return -1;  
    }  
    glfwMakeContextCurrent(window);//设置当前窗体为opengl绘制的舞台

    // 设置窗体大小变化监听
    glfwSetFramebufferSizeCallback(window, frameBufferSizeCallBack); 
    // 设置键盘监听
    glfwSetKeyCallback(window, keyCallback);

    // 使用glad加载当前版本opengl函数
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        printf("gladLoadGLLoader faild\n"); 
        return -1;  
    }

    // 设置opengl视口,清理颜色
    glViewport(0, 0, 800, 600);
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

    while (!glfwWindowShouldClose(window)) {  
        glfwPollEvents();  //接收并分发窗口消息, 检查消息队列是否有需要处理的鼠标、键盘等消息, 如果有的话就将消息批量处理,清空队列

        // 执行opengl画布清理操作
        glClear(GL_COLOR_BUFFER_BIT);

        // 渲染操作

        // 切换双缓存
        glfwSwapBuffers(window);

    }  

    glfwTerminate();  
    return 0;  
}

原文地址:https://blog.csdn.net/qq_51355375/article/details/140577426

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!