OpenGL 簡(jiǎn)介
??OpenGL是一個(gè)由Khronos Group維護(hù)的圖形繪制的規(guī)范
??OpenGL規(guī)范規(guī)定了函數(shù)的執(zhí)行、輸出饲嗽,但是具體的實(shí)現(xiàn)則是由庫(kù)的開(kāi)發(fā)者(通常指顯卡生產(chǎn)商)來(lái)實(shí)現(xiàn)的擅编,不同的庫(kù)實(shí)現(xiàn)可能不一樣
??OpenGL本質(zhì)上是一個(gè)大狀態(tài)機(jī)所踊,通過(guò)改變上下文(context)的變量告訴OpenGL怎么繪圖
創(chuàng)建窗口(GLFW)
創(chuàng)建窗口可以使用GLUT棺禾,SDL蓬蝶,QT读处,GLFW等糊治,這里我用的是GLFW
GLFW
??GLFW是個(gè)開(kāi)源的支持多個(gè)平臺(tái)的庫(kù),支持OpenGL罚舱、Vulkan井辜。提供創(chuàng)建窗口、事件接收等管闷。
GLFW安裝
頭文件添加
#include <GLFW\glfw3.h>
??gcc 在編譯時(shí)需要加入-lGLEW -lglfw3 -lGL -lX11 -lpthread -lXrandr -lXi
粥脚,否則可能出現(xiàn)未定義的引用錯(cuò)誤
待完成
GLAD
??因?yàn)镺penGL只是個(gè)規(guī)范,具體是由顯卡驅(qū)動(dòng)開(kāi)發(fā)商決定包个,很多函數(shù)位置不能在編譯時(shí)決定刷允,自己來(lái)取得地址的話(huà)會(huì)導(dǎo)致代碼很復(fù)雜,所以需要使用GLAD來(lái)幫我們實(shí)現(xiàn)
GLAD配置
??GLAD有一個(gè)在線(xiàn)服務(wù)可以根據(jù)語(yǔ)言碧囊、版本树灶、模式來(lái)獲取我們想要的庫(kù)。打開(kāi)后糯而,語(yǔ)言選擇C/C++破托,模式選擇core,版本選擇3.3(因?yàn)槲矣玫氖?.3版本)
??把生成的壓縮文件解壓歧蒋,里面的glad和KHR目錄放在你的項(xiàng)目頭文件目錄土砂,glad.c也添加到工程中,并在項(xiàng)目引入頭文件
#include <glad/glad.h>
CMakeLists.txt
??由于我使用的CLion創(chuàng)建的項(xiàng)目谜洽,所以也就使用CMake了萝映,CMakeLists.txt部分內(nèi)容如下
添加glad庫(kù)
add_library(glad SHARED ./src/glad/glad.c)
添加stb_image(加載圖片用)
add_library(stb_image SHARED ./src/stb_image/stb_image.cpp)
鏈接庫(kù)(opengl_glfw03是項(xiàng)目可執(zhí)行文件)
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
編譯沒(méi)問(wèn)題的話(huà)就可以創(chuàng)建窗口了
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
開(kāi)始創(chuàng)建窗口
- 初始化GLFW
glfwInit();
- GLFW選項(xiàng)設(shè)置函數(shù)
hint
:需要設(shè)置的選項(xiàng)
value
:需要設(shè)置的值
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);
- 配置多重采樣實(shí)現(xiàn)抗鋸齒
glfwWindowHint(GLFW_SAMPLES,4);
別忘了啟用OpenGL的多重采樣,雖然默認(rèn)是啟用的
glEnable(GL_MULTISAMPLE);
- 創(chuàng)建窗口對(duì)象
width
:窗口寬度
height
:窗口高度
title
:窗口標(biāo)題
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){
// 當(dāng)窗口創(chuàng)建失敗時(shí)中斷并退出
...
glfwTerminate();
return -1;
}
- 將當(dāng)前窗口設(shè)置為主線(xiàn)程上下文
glfwMakeContextCurrent(window);
- 初始化GLAD
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
// 當(dāng)GLAD初始化失敗時(shí)退出
...
glfwTerminate();
return -1;
}
- 添加窗口大小改變回調(diào)
// 聲明回調(diào)函數(shù)
void onFramebufferSizeCallback(GLFWwindow*,int,int);
// 添加回調(diào)
glfwSetFramebufferSizeCallback(window,onFramebufferSizeCallback);
- 在回調(diào)中處理視口變換
x
:左下角x坐標(biāo)
y
:左下角y坐標(biāo)
width
:渲染寬度
height
:渲染高度
glViewport(GLint x,GLint y,GLsizei width,GLsizei height);
void onFramebufferSizeCallback(GLFWwindow *window,int width,int height){
glViewport(0,0,width,height);
}
- 渲染循環(huán)
為了避免一運(yùn)行就退出
while(!glfwWindowShouldClose(window)){
// 交換顏色緩沖
glfwSwapBuffers(window);
// 檢查觸發(fā)事件
glfwPollEvents();
}
- 清除窗口顏色緩沖
red
:紅
green
:綠
blue
:藍(lán)
alpha
:透明通道
glClearColor(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha);
寫(xiě)在處理鍵盤(pán)事件代碼之后
// 用glClearColor設(shè)置的顏色填充
glClearColor(0.5f,0.5f,0.6f,1.0f);
// 清除顏色緩沖
glClear(GL_COLOR_BUFFER_BIT);
- 處理鍵盤(pán)事件
聲明函數(shù)
void onKeyInput(GLFWwindow *);
處理鍵盤(pán)事件寫(xiě)在循環(huán)體內(nèi)部第一行
onKeyInput(window);
void onKeyInput(GLFWwindow *window){
// 判斷ESC按鈕就是否觸發(fā)
if(glfwGetKey(window,GLFW_KEY_ESCAPE)==GLFW_PRESS){
// 觸發(fā)就設(shè)置close為真
glfwSetWindowShouldClose(window,GLFW_TRUE);
}
}
- 清理資源并退出
glfwTerminate();
return 0;
最后
此時(shí)運(yùn)行代碼應(yīng)該會(huì)出現(xiàn)一個(gè)窗口像下面這個(gè)阐虚,按ESC即可退出序臂,后面會(huì)在此基礎(chǔ)上添加很多東西
代碼Github地址