【LearnOpenGL入门学习记录1】窗口、视口和输入 | 您所在的位置:网站首页 › opengl函数库手册 › 【LearnOpenGL入门学习记录1】窗口、视口和输入 |
本文目录
引言1 基础知识1.1 OpenGL1.2 OpenGL上下文1.3 GLFW和GLAD1.4 窗口对象和视口
2 渲染流程及API2.1 初始化GLFW及配置GLFW窗口2.2 创建窗口对象并设为当前进程的主上下文:2.3 初始化GLAD2.4 动态设置视口尺寸2.5 循环渲染2.6 释放已allocate的上下文资源
3 渲染结果4 遇到及待解决的问题4.1 编译时函数名未引用4.2 快速放大窗口时,视口花了4.3 GLFW窗口的配置顺序
引言
1、本专栏为LearnOpenGL的学习笔记,用来记录基础知识、渲染流程和遇到的问题。如果文中理解有误,还请指正。 2、GLFW API手册 3、OpenGL Specification 1 基础知识 1.1 OpenGLOpenGL不是API,而是显卡厂商实现这组API的接口与规范。OpenGL规范严格规定了每个函数该如何执行,以及它们的输出值。至于内部具体每个函数是如何实现(Implement)的,将由OpenGL库的开发者自行决定。 1.2 OpenGL上下文OpenGL上下文(整个渲染视图)是以对象的形式存储的,渲染视图中的每个部分作为该对象中的一个嵌套对象存在,每个对象通过成员变量和成员函数完成其属性的设置,如下所示。 // OpenGL上下文 struct OpenGL_Context { ... object* object_Window_Target; ... }; 1.3 GLFW和GLADGLFW是一个轻量级的OpenGL框架,提供了一套用来管理窗口,读取输入,处理事件等操作的API(说白了就是为视口提供一个可以和用户交互的窗口?)。 GLAD专门加载OpenGL的函数指针的Loading Library,因为OpenGL驱动版本太多编译期无法确定使用的是哪个,因此开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用,使用GLAD管理函数指针可以避免大量的查找函数指针这种重复性代码(实际上这些代码都存在,只是不需要我们再自己写了)。 1.4 窗口对象和视口窗口:视口用来与用户交互的一个中间件 视口:真正的渲染区域 2 渲染流程及API 2.1 初始化GLFW及配置GLFW窗口初始化GLFW:int glfwInit(void) 此函数用于初始化GLFW库,在使用GLFW函数之前必须初始化GLFW。如果成功则返回GLFW_TRUE、失败则返回GLFW_FALSE并在返回之前调用glfwTerminate释放已分配的资源。 配置GLFW窗口:void glfwWindowHint(int hint, int value) 此函数用于配置glfw,通过该函数可以告诉GLFW我们要使用的OpenGL版本和渲染模式。 //配置GLFW窗口 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3); //设置opengl的主版本号 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3); //设置opengl的次版本号 glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE); //使用opengl的核心模式,即库不再向后兼容 //初始化GLFW if(!glfwInit()){ //成功return1 失败return0 std::cout glViewport(0,0,width,height);//根据更新后的窗口,同比更新视口大小 }【Note】OpenGL幕后使用glViewport中定义的位置和宽高进行2D坐标的转换,将OpenGL中的位置坐标转换为你的屏幕坐标。例如,OpenGL中的坐标(-0.5, 0.5)有可能(最终)被映射为屏幕中的坐标(200,450)。注意,处理过的OpenGL坐标范围只为-1到1,因此我们事实上将(-1到1)范围内的坐标映射到(0, 800)和(0, 600)。 2.5 循环渲染我们希望程序在我们主动关闭它之前不断绘制图像并能够接受用户输入。因此,我们需要在程序中添加一个while循环,我们可以把它称之为渲染循环(Render Loop),它能在我们让GLFW退出前一直保持运行。 检测GLFW是否被要求退出:glfwWindowShouldClose() 该函数在每次循环的开始前检查一次GLFW是否被要求退出,如果是的话该函数返回true然后渲染循环便结束了,之后为我们就可以关闭应用程序了。 检测GLFW窗口是否有触发事件:glfwPollEvents() 该函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。 交换缓冲区:glfwSwapBuffers() 该函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上,双缓冲可以有效地避免渲染时的闪烁现象。 检测特定按键是否被按下:glfwSwapBuffers 该函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。 //5、循环渲染 while(!glfwWindowShouldClose(window)){ //检查glfw是否要求退出,如果是return true //输入检测 processInput(window); //当前帧渲染 // 检查并调用事件,交换缓冲 glfwSwapBuffers(window); //交换颜色缓冲(这个缓冲存储着GLFW窗口中没一个像素的颜色值),里面有两个buffer,前缓冲保存最当前帧的输出,后缓冲保存下一阵的渲染指令。避免等待绘制带来的闪烁感。 glfwPollEvents(); }上述代码是GLFW实现循环渲染和输入检测的框架,接着我们在当前帧渲染区域中填入当前帧的渲染代码就完成了逐帧的动态渲染。 视口颜色状态设置函数:glClearColor() 该函数用于设置清空屏幕所用的颜色。 视口颜色状态使用函数:glClear() 该函数使用状态设置函数设置的颜色来清空屏幕(感觉像是把成员变量重新赋值的逻辑?) 2.6 释放已allocate的上下文资源当渲染循环结束后我们需要正确释放/删除之前的分配的所有资源。我们可以在main函数的最后调用glfwTerminate函数来完成。 释放GLFW已分配的资源:void glfwTerminate (void) 该函数将销毁所有剩余的窗口和光标,并释放任何GLFW分配的资源。 3 渲染结果 #include #include #include //帧缓冲大小函数:当用户改变窗口大小时,视口的大小也应该同比调整,所以需要对窗口注册一个回调,使其在每次窗口大小被调整时被调用,以更新视口大小 //实现方式:我们通过在窗口改变时用glfwSetFramebufferSizeCallback()函数来调用这个回调函数 void framebuffer_size_callback(GLFWwindow* window,int width,int height){ glViewport(0,0,width,height);//根据更新后的窗口,同比更新视口大小 } void processInput(GLFWwindow *window){ if(glfwGetKey(window,GLFW_KEY_ESCAPE)==GLFW_PRESS){ glfwSetWindowShouldClose(window,true); } } int main(){ //实例化GLFW窗口 //1、初始化GLFW if(!glfwInit()){ //成功return1 失败return0 std::cout //给glad传入当前系统加载OpenGL函数指针地址的函数,GLFW提供的该函数为:glfwGetProcAddress std::cout |
CopyRight 2018-2019 实验室设备网 版权所有 |