文章目录
窗口的创建
初始化GLFW并进行配置
#include <glad/glad.h>
#include <glfw3.h>
//must include GLAD before GLFW. The include file for GLAD includes the required OpenGL headers(GL/gl.h ... )
int main() {
glfwInit(); //initialize GLFW
//configure the options prefixed with GLFW_
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
return 0;
}
步骤:
- 初始化glfw
- 声明我们使用的OpenGL的最大和最小版本都为3
- 指明使用core-profile(只使用OpenGL特性的子集,没有向后兼容的功能)
要保证OpenGL是3.3版本以上的,查看OpenGL版本的软件。
创建窗口对象
创建的窗口对象容纳了所有的窗口数据(初始化之后的代码段)。
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL_0_Start", NULL, NULL);//window witdth,height,name
if (window == NULL) {
cout << "create window failed" << endl;
glfwTerminate();
return -1;
}
//tell GLFW to make the context of our window the main context on the current threaed
glfwMakeContextCurrent(window);
最后一行代码的目的是让我们窗口的context成为当前线程的主context。
载入GLAD
glfwGetProcAddress根据操作系统提供函数。
//load the address of the OpenGL pointers
//glfwGetProcAddress defines the correct function based on which OS we're compiling for
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
cout << "GLAD initializaion failed!" << endl;
}
定义视口大小
//define the size of the rendering window
glViewport(0, 0, 800, 600);//position, size(in pixels)
定义并注册resize事件
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
准备engines
为了不让应用程序画一帧就关掉窗口,使用while定义render loop。
while (!glfwWindowShouldClose(window)) {
glfwSwapBuffers(window);
glfwPollEvents();
}
- glfwWindowShouldClose检验窗体是否被关闭
- glfwSwapBuffers交换颜色缓存(是一个巨大的包含GLFW窗口的每个像素颜色值的Buffer)
- glfwPollEvents检查是否有事件被触发(键盘、鼠标事件)
此时启动程序可以看到一个黑色的窗口持续显示。
双层缓冲(Double Buffer)
单层缓冲(single buffer)可能导致闪烁(flickering)现象。
Flickering产生的原因
输出结果图并不是即时绘制的,而是从左到右,从上到下逐像素绘制的。这就导致图还没画完就被展示给了用户,导致了artifacts。
Double Buffer 工作原理
分为前(front)缓冲和后(back)缓冲。
- front buffer负责给用户展示绘制的结果。
- 所有命令都在back buffer上执行,以进行下一帧的绘制。
- back buffer的命令执行完毕后,swap前后缓冲,这样就没有Flickering问题了。
关闭窗口并回收分配的资源
在main函数结束前调用glfwTerminate
函数,这个函数清除了所有资源并退出应用程序。
glfwTerminate();
处理输入
在GLFW中进行输入控制,只需要使用几个GLFW的输入函数。
glfwGetKey
函数返回某个按键当前是否被按压。
void processInput(GLFWwindow *window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) //if the button not be pressed,the function return GLFW_RELEASE.
glfwSetWindowShouldClose(window,true);
}
上面的函数表示当按住Escape时,设置GLFW窗口关闭标志。
在准备engines的循环中,swap缓存之前,先调用一下这个函数接收输入事件。
渲染 Rendering
写渲染代码时,在render loop中放置所有的渲染命令,以在每一次帧循环时执行所有渲染命令。
glClearColor(0.3, .6, .5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
- 使用特定的颜色清空屏幕
glClearColor(r,g,b,a)
- 指定想要清除哪种buffer
glClear(GL_COLOR_BUFFER_BIT)
,参数枚举包括GL_COLOR_BUFFER_BIT、GL_DEPTH_BUFFER_BIT、GL_STENCTIL_BUFFER_BIT
。
glClearColor函数是一个状态设置函数,而glClear函数则是一个状态使用的函数。
完整代码
#include <glad/glad.h>
#include <glfw3.h>
#include<iostream>
//must include GLAD before GLFW. The include file for GLAD includes the required OpenGL headers(GL/gl.h ... )
using namespace std;
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) //if the button not be pressed,the function return GLFW_RELEASE.
glfwSetWindowShouldClose(window,true);
}
int main() {
glfwInit(); //initialize GLFW
//configure the options prefixed with GLFW_
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//create the window
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL_0_Start", NULL, NULL);//window witdth,height,name
if (window == NULL) {
cout << "create window failed" << endl;
glfwTerminate();
return -1;
}
//tell GLFW to make the context of our window the main context on the current threaed
glfwMakeContextCurrent(window);
//load the address of the OpenGL pointers
//glfwGetProcAddress defines the correct function based on which OS we're compiling for
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
cout << "GLAD initializaion failed!" << endl;
}
//define the size of the rendering window
glViewport(0, 0, 800, 600);//position, size(in pixels)
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window)) {
processInput(window);
glClearColor(0.3, .6, .5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}