// OpenGL01(你好,窗口)
#include <iostream>
//這裏須要注意頭文件導入順序,不然編譯不能經過
#include "glew.h"
#include "glfw3.h"
/*
使用簡介
1> GLFW是在openGL裏創建窗口用的。跟GLUT/freeglut相似。
2> GLEW是用來管理OpenGL的函數指針的
3> openGL都是跟着驅動來的。只要裝了顯卡驅動,就會有openGL。
4> 通常來講假如用來開發的話,GLFW+GLEW+openGL就夠用了。GLEW是用來智能載入不少openGL擴展函數(extensions)的。
5> 編譯的時候先載入openGL,而後是GLEW,最後是GLFW。假如是windows的話,也許還須要gdi32。 g++ -Wall -g main.cpp -lglfw -lglew32 -lopengl32 之類的。
*/
/*! @brief The function signature for keyboard key callbacks.
*
* This is the function signature for keyboard key callback functions.
*
* @param[in] window The window that received the event.
* @param[in] key The [keyboard key](@ref keys) that was pressed or released.
* @param[in] scancode The system-specific scancode of the key.
* @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
* @param[in] mods Bit field describing which [modifier keys](@ref mods) were
* held down.
*
* @sa @ref input_key
* @sa glfwSetKeyCallback
*
* @since Added in version 1.0.
* @glfw3 Added window handle, scancode and modifier mask parameters.
*
* @ingroup input
*/
//GLFW會在合適的時候調用它,並非由於glfwPollEvents 的觸發
//window:當前的窗口 key:按下的鍵 action:按下仍是釋放 mods:是否有Ctrl、Shift、Alt、Super等按鈕的操作
//這裏咱們監聽到了 鍵盤 esc 被按下去了,而後將windowshouldclose 設置成TRUE,讓引擎結束。
void KeyCallback(GLFWwindow* window,int key,int scancode,int action,int mods){
if (key==GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
//1>爲何須要清空屏幕?
//每個新的渲染開始的時候咱們一般是但願清一下屏,不然咱們老是能看見上一次的渲染結果。
void clearWindow(){
//設置一個顏色來清空屏幕
glClearColor(1, 0.2, 0.2, 1);
//清空函數,目前咱們僅僅指向清空顏色
//可能的緩衝位有GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT。
glClear(GL_COLOR_BUFFER_BIT);
}
int main(int argc, const char * argv[]) {
//1>初始化glfw並設置
//實例化glfw
if (glfwInit()!=GLFW_TRUE) {
std::cout<<"初始化glfw失敗"<<std::endl;
return -1;
}
//配置glfw
//主版本號設置
//這裏須要注意的是,咱們的主次版本號是根據OpenGL來的,目前咱們用的是2.1版本(目前大部分教程都是針對3.3以上的),因此設置主次版本應該以OpenGL版原本,而不是glfw的版本
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
//次版本號設置
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
//設置不可改變大小
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//2>窗口設置並設置
//建立窗口對象
//GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share)
//參數依次爲:窗口的寬,窗口的高,窗口的title,未知,未知。
GLFWwindow * window = glfwCreateWindow(800, 600, "hello window", nullptr, nullptr);
if (window==nullptr) {
std::cout<<"初始化窗口失敗"<<std::endl;
return -1;
}
//通知glfw將窗口的上下文設置成當前線程的主上下文
glfwMakeContextCurrent(window);
//3>glew設置並設置
//glew管理OpenGL的函數指針。glewExperimental設置成TRUE是爲了讓glew管理OpenGL函數指針的時候更多的使用現代化的技術,若是設置成FALSE可能會在使用OpenGL核心模式時出現問題。
glewExperimental = GL_TRUE;
if (glewInit()!=GLEW_OK) {
std::cout<<"初始化glew失敗"<<std::endl;
return -1;
}
//4>視口設置viewport(告訴OpenGL渲染的窗口的尺寸大小,及渲染的位置。即:設置窗口的維度)
//獲取窗口大小
int width,height;
glfwGetFramebufferSize(window, &width, &height);
//給視口視圖設置位置及其大小
//glViewport (GLint x, GLint y, GLsizei width, GLsizei height)
//x,y 表示視口視圖相對於窗口的位置(0,0)表示在左下角;width,height是視口視圖的寬高,這裏咱們從窗口獲取大小而不直接用窗口的800*600 是爲了讓他能在高的DPI屏幕上(例如Apple的視網膜顯示屏)也能正常工做
//固然,咱們也能夠設置寬高小一點 這樣在窗口上就會小一點顯示
//OpenGL的座標範圍是【-1,1】,對應的範圍映射的座標是【0,800】,【0,600】
glViewport(0, 0, width, height);
//5>註冊咱們函數回調
glfwSetKeyCallback(window, KeyCallback);
//6>準備引擎。目的是爲了函數可以不斷的繪製並能接收用戶輸入。而不是渲染了一次就程序退出關閉窗口了
while (!glfwWindowShouldClose(window)) {
//檢查有沒有什麼事件被觸發(鍵盤,鼠標等),而後調用對應的回到函數
glfwPollEvents();
//7>這裏就是咱們最終要的渲染指令了
//這裏咱們寫一個自定義顏色清空屏幕測試
clearWindow();
//交換顏色緩衝。
//爲何使用交換顏色緩衝?
//應用程序使用單緩衝繪圖時可能會產生圖像閃爍的問題,由於圖像是從左到右,由上到下逐像素繪製而成,不是一瞬間就展現給用戶。因此咱們一般使用的是雙緩衝渲染,前緩衝保存着最終渲染好的圖像用於窗口顯示,而渲染指令都會在後緩衝上繪製,當全部的渲染指令完成之後咱們將先後緩衝交換(swap),這樣圖像就顯示出來了。
glfwSwapBuffers(window);
}
//6>當循環結束後,咱們須要釋放glfw的內存
glfwTerminate();
return 0;
}