OpenGL+VS2019代码搭建

 状态机

OpenGL自身是一个巨大的状态机,变量(描述该如何操作)的大集合

OpenGL的状态通常被称为上下文(Context)。

状态设置函数(State-changing Function)

状态应用的函数(State-using Function)

通过改变一些上下文变量来改变 OpenGL状态,从而告诉OpenGL如何去绘图

对象

一个对象是指一些选项的集合,代表OpenGL状态的一个子集

例如:可以用一个子集来代表绘图窗口的设置:设置它的大小、支持的颜色位数等等。可以把对象看做一个C风格的结构体:

 结构如下:

struct object_name

{ GLfloat option1;

GLuint option2;

GLchar[] name;

};

通常把OpenGL上下文比作一个大的结构体,包含很多子集:

// OpenGL的状态

struct OpenGL_Context

{ ...

object* object_Window_Target;

...

};

 但是需要注意的是:

当前状态只有一份,如果每次显示不同的效果,都重新配置会很麻烦。

这时候我们就需要一些小助理(对象),帮忙记录某些状态信息。以便复用。

如果有10种子集,每个子集有10种不同的状态集合,那么我们将需要100个小助理(对象)

复制代码
// 创建对象 
GLuint objectId = 0; 
//给小助理(对象)一个编号
glGenObject(1, &objectId); 
// 绑定对象至上下文 
glBindObject(GL_WINDOW_TARGET, objectId);
 
// 设置GL_WINDOW_TARGET对象的一些选项 下面这些设置都是给对象objectId 做的设置
glSetObjectOption(GL_WINDOW_TARGET,GL_OPTION_WINDOW_WIDTH, 800); 
glSetObjectOption(GL_WINDOW_TARGET,GL_OPTION_WINDOW_HEIGHT, 600); 

// 将上下文的GL_WINDOW_TARGET对象设回默认 ,此时已经将objectId 对象解绑了,但是这个对象已经存在这个状态机(就是这个大对象集合)中了,
// 所以再次调用glBindObject方法重新绑定的时候,这些选项就会再次生效。还要注意的是我们最好习惯性的使用这个解绑方法,防止未解绑导致出现上一个对象设置的状态出现在了当前对象上。
glBindObject(GL_WINDOW_TARGET, 0);
复制代码

 所以如果我们一开始就需要多个对象,并且对于一些选项有想法的情况,可以直接创建多对象,遍历多次分别设置一些默认的状态。在这个遍历中,以绑定对象和解绑对象分别为开始和结束。

 GLFW+GLAD

 不同操作系统上,创建支持OpenGL的窗口接口不同。需要我们自己处理创建窗口,定义OpenGL上下文以及处理用户输入。不同操作系统,不同显卡获取OpenGL函数的接口也有差异。

 GLFW解决操作系统层面的不同

  •     创建窗口
  •     定义上下文
  •     处理用户输入

GLAD使得代码可以用于不同的OpenGL驱动

  • OpenGL本身只是标准/规范
  • 各个厂家具体实现方式可以不同

VS2019代码搭建

GLFW 第三方库(帮助你支持OpenGL上下文的窗口)

下载地址:https://www.glfw.org/

 

 

 下载解压之后包含了这些文件:

 下面使用vs2019创建一个空项目:

 

 

 然后我们需要配置GLFW,我们在包含目录中将提前下好的GLFW中的图中的文件夹包含进去:

 

 

 还要将和VS2019相关的.lib文件也包含到项目的库目录中:

 

 

 

 还要注意的是在Windows上,还需使用OpenGL库opengl32.lib(随Microsoft SDK一起提供,在安装Visual Studio时默认安装)和glfw3.lib。

 

GLAD使用了一个web服务器,通过输入想要为使用的OpenGL版本和相关信息生成库文件。 转到GLAD服务网站(https://glad.dav1d.de),具体设置如下:

 

点击网站右下方的“GENERATE”,进入下载界面,下载glad.zip文件,解压缩即可使用。

 

 

下载解压之后有下面2个文件夹:

 

首先,配置包含目录:

然后将src文件中的glad.c文件添加到项目中:

 验证是否配置正确

 代码如下:

复制代码
// GLAD的include文件包含所需的OpenGL头文件(如GL/GL.h),因此确保在其他需要OpenGL的头文件(如GLFW)之前包含GLAD。就是#include <glad/glad.h> 放在最前面
#include <glad/glad.h> 
#include <GLFW/glfw3.h>
#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);

int main() {
    // 初始化GLFW,只有初始化完成之后才能够使用GLFW的函数
    glfwInit();
    // GLFW配置设置
    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
    // 创建窗口 大小和名称
    GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
    if (window == NULL) {
        std::cout << "Failed to create GLFW window" << std::endl;
        // 此函数销毁所有剩余的窗口和光标
        glfwTerminate();
        return -1;
    }
    //GLFW将窗口的上下文设置为当前线程的上下文
    glfwMakeContextCurrent(window);
    // 告诉GLFW我们希望每当窗口调整大小的时候调用这个函数
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    //GLAD
    // glad: 加载所有OpenGL函数指针
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    // 渲染循环 一个循环就是一帧 只要是窗体不关闭,就会一直循环
    while (!glfwWindowShouldClose(window)) {
        processInput(window);

        // 在这里,我们将屏幕设置为了类似黑板的深蓝绿色
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //状态设置
        // 调用glClear函数,清除颜色缓冲之后,整个颜色缓冲都会被填充为glClearColor里所设置的颜色。
        glClear(GL_COLOR_BUFFER_BIT); //状态使用
        // glfw: 交换缓冲区 该函数在指定窗口的前后缓冲区交换
        // 前缓冲区:屏幕上显示的图像
        // 后缓冲区:正在渲染的图像
        // glfwSwapBuffers函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),
        // 它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上
        glfwSwapBuffers(window);
        // 轮询IO事件(按键按下 / 释放、鼠标移动等)通过下面方法就可以是得窗体对鼠标做出的动作做出反应,比如关闭,移动窗体等
        glfwPollEvents();
    }
    // glfw: 回收前面分配的GLFW先关资源. 一定要注意,只有关闭窗体之后才会跳出while循环走到这一步!!!
    glfwTerminate();
    return 0;
}
// glfwGetKey函数:需要一个窗口以及一个按键作为输入;函数将会返回这个按键是否正在被按下
void processInput(GLFWwindow* window)
{
    // 如果按下了ESC键,设置窗体的关闭标志为true,代表窗体可以退出
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// 当改变窗口的大小的时候,视口也应该被调整。我们可以对窗口注册一个回调函数(Callback Function),它会在每次窗口大小被调整的时候被调用
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // 设置窗口维度
    // glViewport(前两参数为窗口左下角位置,3.宽度,4.高度)
    glViewport(0, 0, width, height);
}
复制代码

 

 结果:

 

posted @   安静点--  阅读(207)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2021-08-27 数据结构之基于无序链表的集合和映射
点击右上角即可分享
微信分享提示