openGL笔记之环境搭建(二)

基本框架

第一版

自从上一次环境搭建的笔记写完很久之后,今天终于又能继续做笔记了。目前的进度比较混乱,很多资料相互参杂着看,我打算这里先从整体开始,在逐渐向细节填充。这一篇就先记一下框架,也就是借用了GLFW和GLAD来创建窗口,以及之后如何在窗口中绘制自己的内容。

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main() {
    //初始化glfw
    glfwInit();
    //设置当前使用的opengl版本
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    //设置opengl使用的渲染模式(这里是核心模式,也就是opengl3.0以后建议使用的新特性)
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    //mac平台兼容需要前向兼容
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    //创建glfw窗口
    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;
    }
    //将opengl渲染渲染到这个窗口
    glfwMakeContextCurrent(window);

    //通过glad读取对应的opengl函数地址
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    //一直做这个事情
    while (!glfwWindowShouldClose(window)) {
        //设置缓存清除的颜色
        glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
        //清除缓存
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //交换缓存
        glfwSwapBuffers(window);
        //通过glfw调用所有的事件
        glfwPollEvents();
    }
    //关闭窗口
    glfwTerminate();
    return 0;
}

虽然上面这些都不需要深究,但有几个点需要记一下:
1. 使用GLFW创建窗口一定要先初始化GLFW,这是当然的,必须包括的是OpenGL版本、OpenGL渲染模式。
2. 通过GLAD来获取OpenGL的函数地址,这是因为OpenGL本身并没有具体的API实现,真正的实现都是由各硬件厂商提供的,因此需要通过GLAD来获取具体的函数地址,否则,调用OpenGL函数的时候就会因为找不到具体的函数地址而出错了。
3. 在使用GLAD来获取函数地址之前,应当先调用glfwMakeContextCurrent(window)这个函数设置当前的绘制窗口,具体原因尚不明确,只是若非如此将会导致GLAD初始化失败。
4. glfwSwapBuffers(window)和glfwPollEvents()这两个函数是固定套路。

第一版的代码就长这样,加上了注释,忘记了就回来看看。有些函数现在只知道大概作用却不知道具体有什么特点,但是没关系,以后有需要的话再了解。
后面要做的就是给它重构一下,不然很大一堆放在一起太扎眼了。所以,就有了第二版。

第二版

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>


// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

void init();
GLFWwindow* createWindow();
void onDraw(GLFWwindow*);

int main() {
    init();

    onDraw(createWindow());

    glfwTerminate();
    return 0;
}
void onDraw(GLFWwindow* window){
    if(!window)
        return;
    while (!glfwWindowShouldClose(window)) {
        glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
}
void init(){
    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
}
GLFWwindow* createWindow(){
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    glfwMakeContextCurrent(window);

    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window!" << std::endl;
        glfwTerminate();
        return nullptr;
    }

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD!" << std::endl;
        return nullptr;
    }

    return window;
}

这么组织一下的好处在于,逻辑更清晰了,以后只要关注onDraw()函数里的while循环就好了(不用因为main函数里的大量代码而逼死强迫症了)。当然,由于后面的着色器什么的,可能还需要在onDraw前面再加一个函数来处理。
记到这里就差不多了,其他的想法就是把上面这些东西封装到一个类里去,利用C++的一些特性可能会产生更好的效果。嗯,但是目前做这个没什么意义,就先放着吧。

猜你喜欢

转载自blog.csdn.net/zyj_kill/article/details/80991768