Learn OpenGL(一)--简介与创建窗口
OpenGL 简介
OpenGL是一个由Khronos Group维护的图形绘制的规范
OpenGL规范规定了函数的执行、输出,但是具体的实现则是由库的开发者(通常指显卡生产商)来实现的,不同的库实现可能不一样
OpenGL本质上是一个大状态机,通过改变上下文(context)的变量告诉OpenGL怎么绘图
创建窗口(GLFW)
创建窗口可以使用GLUT,SDL,QT,GLFW等,这里我用的是GLFW
GLFW
GLFW是个开源的支持多个平台的库,支持OpenGL、Vulkan。提供创建窗口、事件接收等。
GLFW安装
头文件添加
#include <GLFW\glfw3.h>
gcc 在编译时需要加入-lGLEW -lglfw3 -lGL -lX11 -lpthread -lXrandr -lXi
,否则可能出现未定义的引用错误
待完成
GLAD
因为OpenGL只是个规范,具体是由显卡驱动开发商决定,很多函数位置不能在编译时决定,自己来取得地址的话会导致代码很复杂,所以需要使用GLAD来帮我们实现
GLAD配置
GLAD有一个在线服务可以根据语言、版本、模式来获取我们想要的库。打开后,语言选择C/C++,模式选择core,版本选择3.3(因为我用的是3.3版本)
把生成的压缩文件解压,里面的glad和KHR目录放在你的项目头文件目录,glad.c也添加到工程中,并在项目引入头文件
#include <glad/glad.h>
CMakeLists.txt
由于我使用的CLion创建的项目,所以也就使用CMake了,CMakeLists.txt部分内容如下
添加glad库
add_library(glad SHARED ./src/glad/glad.c)
添加stb_image(加载图片用)
add_library(stb_image SHARED ./src/stb_image/stb_image.cpp)
链接库(opengl_glfw03是项目可执行文件)
target_link_libraries(opengl_glfw03 glad)
target_link_libraries(opengl_glfw03 stb_image)
target_link_libraries(opengl_glfw03 GLEW)
target_link_libraries(opengl_glfw03 glfw3)
target_link_libraries(opengl_glfw03 GL)
target_link_libraries(opengl_glfw03 X11)
target_link_libraries(opengl_glfw03 pthread)
target_link_libraries(opengl_glfw03 Xrandr)
target_link_libraries(opengl_glfw03 Xi)
target_link_libraries(opengl_glfw03 Xxf86vm)
target_link_libraries(opengl_glfw03 Xinerama)
target_link_libraries(opengl_glfw03 Xcursor)
target_link_libraries(opengl_glfw03 rt)
target_link_libraries(opengl_glfw03 m)
target_link_libraries(opengl_glfw03 dl)
main.cpp
编译没问题的话就可以创建窗口了
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
开始创建窗口
- 初始化GLFW
glfwInit();
- GLFW选项设置函数
hint
:需要设置的选项
value
:需要设置的值
glfwWindowHint(int hint,int value);
- 配置上下文版本为3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
- 配置OpenGL模式为
核心(core)
模式
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
- 配置多重采样实现抗锯齿
glfwWindowHint(GLFW_SAMPLES,4);
别忘了启用OpenGL的多重采样,虽然默认是启用的
glEnable(GL_MULTISAMPLE);
- 创建窗口对象
width
:窗口宽度
height
:窗口高度
title
:窗口标题
monitor
:
share
:
glfwCreateWindow(int width,int height,const char *title,GLFWmonitor *monitor,GLFWwindow *share);
GLFWwindow *window=glfwCreateWindow(1200,720,"OpenGL",nullptr,nullptr);
if(window==nullptr){
// 当窗口创建失败时中断并退出
...
glfwTerminate();
return -1;
}
- 将当前窗口设置为主线程上下文
glfwMakeContextCurrent(window);
- 初始化GLAD
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
// 当GLAD初始化失败时退出
...
glfwTerminate();
return -1;
}
- 添加窗口大小改变回调
// 声明回调函数
void onFramebufferSizeCallback(GLFWwindow*,int,int);
// 添加回调
glfwSetFramebufferSizeCallback(window,onFramebufferSizeCallback);
- 在回调中处理视口变换
x
:左下角x坐标
y
:左下角y坐标
width
:渲染宽度
height
:渲染高度
glViewport(GLint x,GLint y,GLsizei width,GLsizei height);
void onFramebufferSizeCallback(GLFWwindow *window,int width,int height){
glViewport(0,0,width,height);
}
- 渲染循环
为了避免一运行就退出
while(!glfwWindowShouldClose(window)){
// 交换颜色缓冲
glfwSwapBuffers(window);
// 检查触发事件
glfwPollEvents();
}
- 清除窗口颜色缓冲
red
:红
green
:绿
blue
:蓝
alpha
:透明通道
glClearColor(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha);
写在处理键盘事件代码之后
// 用glClearColor设置的颜色填充
glClearColor(0.5f,0.5f,0.6f,1.0f);
// 清除颜色缓冲
glClear(GL_COLOR_BUFFER_BIT);
- 处理键盘事件
声明函数
void onKeyInput(GLFWwindow *);
处理键盘事件写在循环体内部第一行
onKeyInput(window);
void onKeyInput(GLFWwindow *window){
// 判断ESC按钮就是否触发
if(glfwGetKey(window,GLFW_KEY_ESCAPE)==GLFW_PRESS){
// 触发就设置close为真
glfwSetWindowShouldClose(window,GLFW_TRUE);
}
}
- 清理资源并退出
glfwTerminate();
return 0;
最后
此时运行代码应该会出现一个窗口像下面这个,按ESC即可退出,后面会在此基础上添加很多东西
代码Github地址