本文主要說明OpenGL技術(shù)中g(shù)lfw的GL上下文與事件處理:
??1.glfw創(chuàng)建GL上下文;
??2.鼠標(biāo)事件;
??3.鍵盤事件;
??4.文件刪除事件;
??5.計(jì)時(shí)操作;
OpenGL上下文創(chuàng)建
關(guān)于上下文
上下文的創(chuàng)建與釋放
-
創(chuàng)建
- 使用
glfwCreateWindow函數(shù)創(chuàng)建窗體的時(shí)候,就同時(shí)創(chuàng)建兩兩個(gè)環(huán)境:窗體與OpenGL或者OpenGL ES上下文;
- 使用
-
釋放
- 上下文的釋放與窗體與整個(gè)應(yīng)用的釋放一起,就是調(diào)用
glfwDestroyWindow或者glfwTerminate函數(shù)的時(shí)候;
- 上下文的釋放與窗體與整個(gè)應(yīng)用的釋放一起,就是調(diào)用
上下文的設(shè)置
- 上下問的設(shè)置使用
glfwWindowHint函數(shù)設(shè)置,并且在調(diào)用glfwCreateWindow之前。
兩個(gè)窗體共享上下文
- 在使用
glfwCreateWindow創(chuàng)建窗體的時(shí)候,指定GLFWwindow * share參數(shù)即可。
離屏上下文
GLFW不支持在沒有關(guān)聯(lián)窗口的情況下創(chuàng)建上下文。但是,可以使用GLFW_VISIBLE窗體創(chuàng)建提示創(chuàng)建具有隱藏窗口的上下文。
但是在Mac系統(tǒng)中,窗體創(chuàng)建的時(shí)候會(huì)自動(dòng)創(chuàng)建菜單條,可以使用
GLFW_COCOA_MENUBAR提示設(shè)置隱藏。
沒有上下文的窗體
- 創(chuàng)建窗體的時(shí)候,可以不創(chuàng)建上下文,只要使用
GLFW_CLIENT_API提示的值為:GLFW_NO_API。 - 沒有上下文的窗體不能傳遞給如下兩個(gè)函數(shù):
glfwMakeContextCurrentglfwSwapBuffers
當(dāng)前上下文
-
在進(jìn)行OpenGL或OpenGL ES調(diào)用之前,需要具有正確類型的當(dāng)前上下文。
- 一個(gè)上下文一次只能是單個(gè)線程的當(dāng)前上下文,而一個(gè)線程一次只能有一個(gè)當(dāng)前上下文。
- 在線程之間移動(dòng)上下文時(shí),必須先使舊線程上的上下文變成非當(dāng)前,然后使其成為新線程上的當(dāng)前上下文(否則兩個(gè)線程都是當(dāng)前上下文,就麻煩了)。
- 設(shè)置當(dāng)前上下文,使用函數(shù)
glfwMakeContextCurrent - 返回當(dāng)前上下文,使用函數(shù)
glfwGetCurrentContext
glfwMakeContextCurrent函數(shù)說明
void glfwMakeContextCurrent ( GLFWwindow * window )
- glfwGetCurrentContext函數(shù)說明
GLFWwindow* glfwGetCurrentContext ( void )
- 下面幾個(gè)函數(shù)調(diào)用,必須有當(dāng)前上下文,否則會(huì)產(chǎn)生錯(cuò)誤
GLFW_NO_CURRENT_CONTEXT:- glfwSwapInterval
- glfwExtensionSupported
- glfwGetProcAddress
關(guān)于OpenGL的擴(kuò)展
-
關(guān)于擴(kuò)展
- OpenGL和OpenGLES的一個(gè)好處是它們的可擴(kuò)展性。硬件供應(yīng)商可能在其實(shí)現(xiàn)中包含擴(kuò)展,這些擴(kuò)展在新版本的OpenGL或OpenGL ES規(guī)范中包含該功能之前對(duì)API進(jìn)行擴(kuò)展,并且某些擴(kuò)展永遠(yuǎn)不會(huì)包含在其中,并且在它們過時(shí)之前一直作為擴(kuò)展保留。
- OpenGL和Direct3D比較起來,最大的一個(gè)長(zhǎng)處就是其擴(kuò)展機(jī)制。硬件廠商開發(fā)出一個(gè)新功能,可以針對(duì)新功能開發(fā)OpenGL擴(kuò)展,軟件開發(fā)人員通過這個(gè)擴(kuò)展就可以使用新的硬件功能。所以雖然顯卡的發(fā)展速度比OpenGL版本更新速度快得多,但程序員仍然可以通過OpenGL使用最新的硬件功能。而Direct3D則沒有擴(kuò)展機(jī)制,硬件的新功能要等到微軟發(fā)布新版DirectX后才可能支持。
-
glad擴(kuò)展
https://glad.dav1d.de
在上下文上開始3D繪制
- 基本步驟是:
- 創(chuàng)建上下文(通過創(chuàng)建窗體實(shí)現(xiàn))
- 設(shè)置當(dāng)前上下文;
- 初始化OpenGL
- 開始繪制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 創(chuàng)建窗體
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗體", NULL, NULL);
// 1. 第一步:設(shè)置當(dāng)前上下文
glfwMakeContextCurrent(window);
// 2. 第二部:初始化OpenGL
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失敗:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 設(shè)置清屏顏色
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 釋放
glfwTerminate();
return 0;
}
// 編譯命令:g++ -omain trangle.cpp -lglfw -lglew -framework opengl
- 運(yùn)行效果:
- 窗體上的清屏繪制
鍵盤事件
鍵盤事件實(shí)現(xiàn)
- 鍵盤事件使用回調(diào)函數(shù)實(shí)現(xiàn):
glfwSetKeyCallback
- 函數(shù)說明:
GLFWkeyfun glfwSetKeyCallback (
GLFWwindow * window,
GLFWkeyfun cbfun
)
- 回調(diào)函數(shù)GLFWkeyfun原型說明
typedef void(* GLFWkeyfun) (GLFWwindow *, int, int, int, int)
- 參數(shù)說明:
- window :發(fā)生事件的窗體
- key :激發(fā)的鍵值
- scancode :鍵值的系統(tǒng)掃描碼
- action:動(dòng)作GLFW_PRESS, GLFW_RELEASE or GLFW_REPEAT.
- mods: 輔助鍵ALT,CTRL,SHIFT,META等
- 事件實(shí)現(xiàn)代碼
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
void cb_key(GLFWwindow * win, int key, int code, int action, int mods){
printf("key:%d, code:%d, action:%d, mods:%d\n", key, code, action, mods);
}
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 創(chuàng)建窗體
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗體", NULL, NULL);
// 處理事件
glfwSetKeyCallback(window, cb_key);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失敗:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 設(shè)置清屏顏色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 釋放
glfwTerminate();
return 0;
}
// 編譯命令:g++ -omain gl02_key_event.cpp -lglfw -lglew -framework opengl
鍵值定義
#define GLFW_KEY_UNKNOWN -1
#define GLFW_KEY_SPACE 32
#define GLFW_KEY_APOSTROPHE 39 /* ' */
#define GLFW_KEY_COMMA 44 /* , */
#define GLFW_KEY_MINUS 45 /* - */
#define GLFW_KEY_PERIOD 46 /* . */
#define GLFW_KEY_SLASH 47 /* / */
#define GLFW_KEY_0 48
#define GLFW_KEY_1 49
#define GLFW_KEY_2 50
#define GLFW_KEY_3 51
#define GLFW_KEY_4 52
#define GLFW_KEY_5 53
#define GLFW_KEY_6 54
#define GLFW_KEY_7 55
#define GLFW_KEY_8 56
#define GLFW_KEY_9 57
#define GLFW_KEY_SEMICOLON 59 /* ; */
#define GLFW_KEY_EQUAL 61 /* = */
#define GLFW_KEY_A 65
#define GLFW_KEY_B 66
#define GLFW_KEY_C 67
#define GLFW_KEY_D 68
#define GLFW_KEY_E 69
#define GLFW_KEY_F 70
#define GLFW_KEY_G 71
#define GLFW_KEY_H 72
#define GLFW_KEY_I 73
#define GLFW_KEY_J 74
#define GLFW_KEY_K 75
#define GLFW_KEY_L 76
#define GLFW_KEY_M 77
#define GLFW_KEY_N 78
#define GLFW_KEY_O 79
#define GLFW_KEY_P 80
#define GLFW_KEY_Q 81
#define GLFW_KEY_R 82
#define GLFW_KEY_S 83
#define GLFW_KEY_T 84
#define GLFW_KEY_U 85
#define GLFW_KEY_V 86
#define GLFW_KEY_W 87
#define GLFW_KEY_X 88
#define GLFW_KEY_Y 89
#define GLFW_KEY_Z 90
#define GLFW_KEY_LEFT_BRACKET 91 /* [ */
#define GLFW_KEY_BACKSLASH 92 /* \ */
#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */
#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */
#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
#define GLFW_KEY_ESCAPE 256
#define GLFW_KEY_ENTER 257
#define GLFW_KEY_TAB 258
#define GLFW_KEY_BACKSPACE 259
#define GLFW_KEY_INSERT 260
#define GLFW_KEY_DELETE 261
#define GLFW_KEY_RIGHT 262
#define GLFW_KEY_LEFT 263
#define GLFW_KEY_DOWN 264
#define GLFW_KEY_UP 265
#define GLFW_KEY_PAGE_UP 266
#define GLFW_KEY_PAGE_DOWN 267
#define GLFW_KEY_HOME 268
#define GLFW_KEY_END 269
#define GLFW_KEY_CAPS_LOCK 280
#define GLFW_KEY_SCROLL_LOCK 281
#define GLFW_KEY_NUM_LOCK 282
#define GLFW_KEY_PRINT_SCREEN 283
#define GLFW_KEY_PAUSE 284
#define GLFW_KEY_F1 290
#define GLFW_KEY_F2 291
#define GLFW_KEY_F3 292
#define GLFW_KEY_F4 293
#define GLFW_KEY_F5 294
#define GLFW_KEY_F6 295
#define GLFW_KEY_F7 296
#define GLFW_KEY_F8 297
#define GLFW_KEY_F9 298
#define GLFW_KEY_F10 299
#define GLFW_KEY_F11 300
#define GLFW_KEY_F12 301
#define GLFW_KEY_F13 302
#define GLFW_KEY_F14 303
#define GLFW_KEY_F15 304
#define GLFW_KEY_F16 305
#define GLFW_KEY_F17 306
#define GLFW_KEY_F18 307
#define GLFW_KEY_F19 308
#define GLFW_KEY_F20 309
#define GLFW_KEY_F21 310
#define GLFW_KEY_F22 311
#define GLFW_KEY_F23 312
#define GLFW_KEY_F24 313
#define GLFW_KEY_F25 314
#define GLFW_KEY_KP_0 320
#define GLFW_KEY_KP_1 321
#define GLFW_KEY_KP_2 322
#define GLFW_KEY_KP_3 323
#define GLFW_KEY_KP_4 324
#define GLFW_KEY_KP_5 325
#define GLFW_KEY_KP_6 326
#define GLFW_KEY_KP_7 327
#define GLFW_KEY_KP_8 328
#define GLFW_KEY_KP_9 329
#define GLFW_KEY_KP_DECIMAL 330
#define GLFW_KEY_KP_DIVIDE 331
#define GLFW_KEY_KP_MULTIPLY 332
#define GLFW_KEY_KP_SUBTRACT 333
#define GLFW_KEY_KP_ADD 334
#define GLFW_KEY_KP_ENTER 335
#define GLFW_KEY_KP_EQUAL 336
#define GLFW_KEY_LEFT_SHIFT 340
#define GLFW_KEY_LEFT_CONTROL 341
#define GLFW_KEY_LEFT_ALT 342
#define GLFW_KEY_LEFT_SUPER 343
#define GLFW_KEY_RIGHT_SHIFT 344
#define GLFW_KEY_RIGHT_CONTROL 345
#define GLFW_KEY_RIGHT_ALT 346
#define GLFW_KEY_RIGHT_SUPER 347
#define GLFW_KEY_MENU 348
#define GLFW_KEY_LAST GLFW_KEY_MENU
修飾鍵定義
#define GLFW_MOD_SHIFT 0x0001
#define GLFW_MOD_CONTROL 0x0002
#define GLFW_MOD_ALT 0x0004
#define GLFW_MOD_SUPER 0x0008
#define GLFW_MOD_CAPS_LOCK 0x0010
#define GLFW_MOD_NUM_LOCK 0x0020
鍵值轉(zhuǎn)換為掃描碼
- 使用函數(shù)
- glfwGetKeyScancode函數(shù)說明
int glfwGetKeyScancode ( int key )
獲取鍵值的狀態(tài)
- 獲取某個(gè)鍵在制定窗體最后的狀態(tài),用來判定一個(gè)鍵是否按下,還是釋放:
glfwGetKey。
- glfwGetKey函數(shù)說明
int glfwGetKey (
GLFWwindow * window,
int key
)
-
GLFW_STICKY_KEYS粘附鍵設(shè)置
如果模式是GLFW_STICKY_KEYS,則該值必須為GLFW_TRUE才能啟用粘滯鍵,或者GLFW_FALSE才能禁用該模式。
如果啟用了粘滯鍵,按鍵將確保下次調(diào)用glfwGetKey時(shí)返回GLFW_PRESS,即使在調(diào)用之前已釋放該鍵。當(dāng)您只關(guān)心按鍵是否已按下,而不關(guān)心按鍵的時(shí)間或順序時(shí),這一點(diǎn)非常有用。
設(shè)置輸入模式使用:
glfwSetInputMode
glfwSetInputMode函數(shù)說明:
void glfwSetInputMode (
GLFWwindow * window,
int mode,
int value )
- 其中的mode定義只能是如下值:
- GLFW_CURSOR:這個(gè)只能設(shè)置為:GLFW_CURSOR_NORMAL,GLFW_CURSOR_HIDDEN,GLFW_CURSOR_DISABLED。
- GLFW_STICKY_KEYS,
- GLFW_STICKY_MOUSE_BUTTONS,
- GLFW_LOCK_KEY_MODS,
- GLFW_RAW_MOUSE_MOTION
文件輸入
- 使用glfwSetCharCallback函數(shù)實(shí)現(xiàn)文本輸入,既輸入的是文本,包含unicode字符(一般是UTF-8編碼)。
- glfwSetCharCallback函數(shù)說明:
GLFWcharfun glfwSetCharCallback (
GLFWwindow * window,
GLFWcharfun cbfun
)
- 回調(diào)函數(shù)GLFWcharfun原型說明
typedef void(* GLFWcharfun) (GLFWwindow *, unsigned int)
- 文本輸入的例子代碼
- 包含UTF-8字符的輸出;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <sstream>
using namespace std;
// 把codeppint轉(zhuǎn)換為native字符。
void utf8chr(int cp, char c[5]){ //一個(gè)unicode最多占5個(gè)字節(jié)。
// char c[5]={ 0x00,0x00,0x00,0x00,0x00 };
if (cp<=0x7F) { // 127的常規(guī)字符
c[0] = cp;
}
else if(cp<=0x7FF) {
c[0] = (cp>>6)+192;
c[1] = (cp&63)+128;
}
else if(0xd800<=cp && cp<=0xdfff) {
// 無效utf-8的codepoint區(qū)
} //invalid block of utf8
else if(cp<=0xFFFF) {
c[0] = (cp>>12)+224;
c[1]= ((cp>>6)&63)+128;
c[2]=(cp&63)+128; }
else if(cp<=0x10FFFF) {
c[0] = (cp>>18)+240;
c[1] = ((cp>>12)&63)+128;
c[2] = ((cp>>6)&63)+128;
c[3]=(cp&63)+128;
}
}
void cb_char(GLFWwindow *win, unsigned int ch){
char c[5]={ 0x00,0x00,0x00,0x00,0x00 }; // 一個(gè)unicode字符最多4字節(jié),包含一個(gè)空終止符。
utf8chr(ch, c);
printf("輸入的字符:%s\n", c);
}
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 創(chuàng)建窗體
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗體", NULL, NULL);
glfwSetCharCallback (window, cb_char);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失敗:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 設(shè)置清屏顏色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 釋放
glfwTerminate();
return 0;
}
// 編譯命令:g++ -omain gl04_char.cpp -lglfw -lglew -framework opengl
- 其中utf8chr函數(shù)是實(shí)現(xiàn)把codepoint轉(zhuǎn)換為本地字符串。
- codepoint轉(zhuǎn)換為本地字符串最多4字節(jié)就是int32整數(shù),當(dāng)然使用5的長(zhǎng)度是保證最后那個(gè)NULL字符。
鍵的名字
- 上面對(duì)codepint解碼,如果不了解codeoint與unicode,不了解utf-8的編碼規(guī)則,一般不太容易理解。
- GLFW提供函數(shù)處理:
glfwGetKeyName
- glfwGetKeyName函數(shù)說明
const char* glfwGetKeyName (
int key,
int scancode
)
- 如果key是GLFW_KEY_UNKNOWN,則對(duì)scancode解釋。對(duì)key解釋,則scancode為0。
- glfwGetKeyName函數(shù)使用例子
// glfwSetKeyCallback(window, cb_key);
void cb_key(GLFWwindow * win, int key, int code, int action, int mods){
const char *str_ch = glfwGetKeyName(key, code);
printf("glfwGetKeyName:%s\n", str_ch);
}
鼠標(biāo)事件
光標(biāo)位置
- 鼠標(biāo)的光標(biāo)位置通過回調(diào)傳遞,回調(diào)函數(shù)通過函數(shù)
glfwSetCursorPosCallback設(shè)置; - 也可以使用函數(shù)
glfwGetCursorPos直接獲取鼠標(biāo)位置。
- glfwSetCursorPosCallback函數(shù)說明
GLFWcursorposfun glfwSetCursorPosCallback (
GLFWwindow * window,
GLFWcursorposfun cbfun
)
- 回調(diào)函數(shù)GLFWcursorposfun的原型說明
typedef void(* GLFWcursorposfun) (GLFWwindow *, double, double)
- glfwGetCursorPos函數(shù)說明
void glfwGetCursorPos (
GLFWwindow * window,
double * xpos,
double * ypos
)
光標(biāo)模式
- glfwSetInputMode函數(shù)可以控制鼠標(biāo)光標(biāo)模式
void glfwSetInputMode (
GLFWwindow * window,
int mode,
int value
)
- 其中mode設(shè)置為光標(biāo)的模式,光標(biāo)模式包含3個(gè)值
- GLFW_CURSOR,其值為:
- GLFW_CURSOR_NORMAL:正常
- GLFW_CURSOR_HIDDEN:隱藏
- GLFW_CURSOR_DISABLED:隱藏和抓取光標(biāo),提供虛擬和無限的光標(biāo)移動(dòng)。
- GLFW_CURSOR,其值為:
鼠標(biāo)原生動(dòng)作
禁用光標(biāo)時(shí),可以啟用原生(未縮放和未加速)鼠標(biāo)運(yùn)動(dòng)(如果可用)。
原生鼠標(biāo)運(yùn)動(dòng)更接近鼠標(biāo)在曲面上的實(shí)際運(yùn)動(dòng)。它不受應(yīng)用于桌面光標(biāo)運(yùn)動(dòng)的縮放和加速的影響。該處理適用于光標(biāo),而原生運(yùn)動(dòng)更適合控制例如3D相機(jī)。因此,只有在禁用光標(biāo)時(shí)才提供原生鼠標(biāo)運(yùn)動(dòng)。
調(diào)用glfwRawMouseMotionSupported函數(shù)檢查當(dāng)前機(jī)器是否提供原始運(yùn)動(dòng),并將GLFW_RAW_MOUSE_MOTION輸入模式設(shè)置為啟用。
默認(rèn)情況下禁用。
光標(biāo)位置與模式的使用例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
void cb_pos(GLFWwindow *win, double x, double y){
char title[50];
bzero(title, sizeof(title));
sprintf(title, "坐標(biāo):(%8.2f,%8.2f)", x, y);
glfwSetWindowTitle(win, title);
double xpos, ypos;
glfwGetCursorPos(win, &xpos, &ypos); //與上面?zhèn)鬟f的位置完全一樣。
printf("坐標(biāo):(%8.2f,%8.2f)\n", xpos, ypos);
}
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 創(chuàng)建窗體
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗體", NULL, NULL);
// 鼠標(biāo)光標(biāo)模式
// glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
if (glfwRawMouseMotionSupported()){
printf("原生鼠標(biāo)模式\n");
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
}else{
printf("原生不支持鼠標(biāo)模式\n");
}
// 處理事件
glfwSetCursorPosCallback(window, cb_pos);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失敗:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 設(shè)置清屏顏色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 釋放
glfwTerminate();
return 0;
}
// 編譯命令:g++ -omain gl06_cursor.cpp -lglfw -lglew -framework opengl
光標(biāo)對(duì)象
創(chuàng)建光標(biāo)
- 光標(biāo)對(duì)象是一個(gè)結(jié)構(gòu)體
typedef struct GLFWcursor GLFWcursor
創(chuàng)建標(biāo)準(zhǔn)光標(biāo)
- 創(chuàng)建標(biāo)準(zhǔn)光標(biāo)使用glfwCreateStandardCursor函數(shù)
- glfwCreateStandardCursor函數(shù)說明
GLFWcursor* glfwCreateStandardCursor(int shape)
- 創(chuàng)建好的光標(biāo)使用下面的設(shè)置光標(biāo)函數(shù)設(shè)置即可使用。
- 標(biāo)準(zhǔn)光標(biāo)類型
#define GLFW_ARROW_CURSOR 0x00036001
#define GLFW_IBEAM_CURSOR 0x00036002
#define GLFW_CROSSHAIR_CURSOR 0x00036003
#define GLFW_HAND_CURSOR 0x00036004
#define GLFW_HRESIZE_CURSOR 0x00036005
#define GLFW_VRESIZE_CURSOR 0x00036006
創(chuàng)建定制光標(biāo)
- 自定義光標(biāo)是使用glfwCreateCursor函數(shù)創(chuàng)建的,它返回創(chuàng)建的光標(biāo)對(duì)象的句柄。
- glfwCreateCursor函數(shù)說明
GLFWcursor* glfwCreateCursor (
const GLFWimage * image,
int xhot,
int yhot //光標(biāo)的參照點(diǎn)(熱點(diǎn)hotspot)
)
釋放光標(biāo)
- 使用glfwDestroyCursor函數(shù)釋放光標(biāo)
void glfwDestroyCursor ( GLFWcursor * cursor )
設(shè)置窗體光標(biāo)
- 當(dāng)創(chuàng)建好光標(biāo)后,就可以設(shè)置光標(biāo)來使用,該函數(shù)為
glfwSetCursor:
- glfwSetCursor函數(shù)說明
void glfwSetCursor (
GLFWwindow * window,
GLFWcursor * cursor
)
使用光標(biāo)對(duì)象的例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 創(chuàng)建窗體
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗體", NULL, NULL);
// 創(chuàng)建光標(biāo)對(duì)象
GLFWcursor *cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
// 創(chuàng)建一個(gè)定制光標(biāo)
unsigned char pixels[16 * 16 * 4]; // 光標(biāo)的圖像數(shù)據(jù)
memset(pixels, 0xff, sizeof(pixels)); // 圖像結(jié)構(gòu)體
GLFWimage image;
image.width = 16;
image.height = 16;
image.pixels = pixels;
GLFWcursor* c_cursor = glfwCreateCursor(&image, 0, 0); // 使用圖像創(chuàng)建光標(biāo)
// 設(shè)置光標(biāo)
// glfwSetCursor(window, cursor);
glfwSetCursor(window, c_cursor);
// 釋放光標(biāo)
// glfwDestroyCursor(cursor); // 釋放光標(biāo),光標(biāo)恢復(fù)成缺省光標(biāo)
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失敗:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 設(shè)置清屏顏色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 釋放
glfwTerminate();
return 0;
}
// 編譯命令:g++ -omain gl07_cursor_object.cpp -lglfw -lglew -framework opengl
光標(biāo)進(jìn)出窗體事件
- 光標(biāo)進(jìn)出狀態(tài)通過兩種方式:
- 回調(diào)的事件方式:
glfwSetCursorEnterCallback; - 查詢獲取方式:
glfwGetWindowAttrib+GLFW_HOVERED;
- 回調(diào)的事件方式:
- glfwSetCursorEnterCallback函數(shù)說明
GLFWcursorenterfun glfwSetCursorEnterCallback (
GLFWwindow * window,
GLFWcursorenterfun cbfun
)
- 回調(diào)函數(shù)GLFWcursorenterfun原型說明
typedef void(* GLFWcursorenterfun) (GLFWwindow *, int)
// 第二個(gè)參數(shù)是GLFW_TRUE:進(jìn),否則GLFW_FALSE:出
鼠標(biāo)按鈕輸入
鼠標(biāo)按鈕事件處理
- 這是通過回調(diào)函數(shù)的方式實(shí)現(xiàn):
glfwSetMouseButtonCallback
- glfwSetMouseButtonCallback函數(shù)說明
GLFWmousebuttonfun glfwSetMouseButtonCallback (
GLFWwindow * window,
GLFWmousebuttonfun cbfun
- GLFWmousebuttonfun回調(diào)函數(shù)原型說明
typedef void(* GLFWmousebuttonfun) (GLFWwindow *, int, int, int)
// 第二個(gè)參數(shù):button
// 第三個(gè)參數(shù):action:GLFW_PRESS 或者 GLFW_RELEASE
// 第四個(gè)參數(shù):mods:輔助鍵狀態(tài)
- 鼠標(biāo)按鈕定義
#define GLFW_MOUSE_BUTTON_1 0
#define GLFW_MOUSE_BUTTON_2 1
#define GLFW_MOUSE_BUTTON_3 2
#define GLFW_MOUSE_BUTTON_4 3
#define GLFW_MOUSE_BUTTON_5 4
#define GLFW_MOUSE_BUTTON_6 5
#define GLFW_MOUSE_BUTTON_7 6
#define GLFW_MOUSE_BUTTON_8 7
#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
鼠標(biāo)按鈕的輪詢
- 就是鼠標(biāo)輸入的另外一種方式:輪詢,不是聽過事件;而是通過函數(shù)調(diào)用來查詢狀態(tài)。
- 查詢函數(shù)是:
glfwGetMouseButton
- 查詢函數(shù)是:
- glfwGetMouseButton函數(shù)說明
int glfwGetMouseButton (
GLFWwindow * window,
int button
)
-
返回值是:
- GLFW_PRESS :按下過;
- GLFW_RELEASE:沒有按下過;
參數(shù)button就是需要對(duì)按下判定的按鈕。
- 為了防止在輪詢的時(shí)候,按下動(dòng)作已經(jīng)完成,這樣輪詢?nèi)菀族e(cuò)失那次鼠標(biāo)按鈕操作,解決這個(gè)問題與鍵盤的處理一樣,通過設(shè)置輸入模式來解決。
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GLFW_TRUE);
鼠標(biāo)滾輪輸入
- 鼠標(biāo)滾輪事件也是回調(diào)函數(shù)的方式來實(shí)現(xiàn)輸入與處理。
- 函數(shù)是:glfwSetScrollCallback
- glfwSetScrollCallback 函數(shù)說明
GLFWscrollfun glfwSetScrollCallback (
GLFWwindow * window,
GLFWscrollfun cbfun
)
- 回調(diào)函數(shù)GLFWscrollfun原型說明
typedef void(* GLFWscrollfun) (GLFWwindow *, double, double)
鼠標(biāo)進(jìn)出、滾輪與按鈕事件的例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
// 鼠標(biāo)進(jìn)出回調(diào)觸發(fā)函數(shù)
void cursor_enter_callback(GLFWwindow *win, int enter_or_leave){
if (enter_or_leave){
printf("鼠標(biāo)進(jìn)入!\n");
}
else{
printf("鼠標(biāo)出去!\n");
}
}
// 鼠標(biāo)按鈕
void mouse_button_callback(GLFWwindow *win, int button, int action, int mods){
printf("鼠標(biāo)按鈕:button=%d,action=%d,mods=%d\n", button, action, mods);
}
// 鼠標(biāo)滾輪
void scroll_callback(GLFWwindow *win, double xoffset, double yoffset){
printf("鼠標(biāo)滾輪:xoffset=%8.2f,yoffset=%8.2f\n", xoffset, yoffset);
}
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 創(chuàng)建窗體
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗體", NULL, NULL);
// 鼠標(biāo)的粘附輸入模式
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GLFW_TRUE);
// 鼠標(biāo)進(jìn)出判定
glfwSetCursorEnterCallback(window, cursor_enter_callback);
// 鼠標(biāo)按鈕操作判定
glfwSetMouseButtonCallback(window, mouse_button_callback);
// 鼠標(biāo)滾輪
glfwSetScrollCallback(window, scroll_callback);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失敗:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// move輪詢
if (glfwGetWindowAttrib(window, GLFW_HOVERED)){
printf("輪詢:進(jìn)入\n");
}
else{
printf("輪詢:出去\n");
}
//按鍵輪詢
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
if(state == GLFW_PRESS){
printf("左鍵按下!\n");
}
// 3. 設(shè)置清屏顏色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 釋放
glfwTerminate();
return 0;
}
// 編譯命令:g++ -omain gl08_button_scroll_move.cpp -lglfw -lglew -framework opengl
文件刪除事件
- 一旦用戶刪除文件,可以通過函數(shù)
glfwSetDropCallback處理;
- glfwSetDropCallback函數(shù)說明
GLFWdropfun glfwSetDropCallback (
GLFWwindow * window,
GLFWdropfun cbfun
)
- 回調(diào)函數(shù)GLFWdropfun原型說明
typedef void(* GLFWdropfun) (GLFWwindow *, int, const char **)
// 第二個(gè)參數(shù):count:刪除文件個(gè)數(shù)
// 第三個(gè)參數(shù):paths:返回刪除的文件列表
時(shí)間計(jì)時(shí)
- GLFW提供四個(gè)與時(shí)間有關(guān)的函數(shù):
- glfwGetTime:獲取從glfwInit初始化以來的時(shí)間,單位是秒;
- glfwSetTime:修改從glfwInit初始化以來的時(shí)間,單位是秒;
- glfwGetTimerValue:獲取真實(shí)的定時(shí)器的時(shí)間值,單位是
秒;
- glfwGetTimerFrequency:獲取時(shí)間頻率;
- 注意:
- 四個(gè)函數(shù)比較簡(jiǎn)單,這里不詳細(xì)說明,下面是使用例子。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 創(chuàng)建窗體
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗體", NULL, NULL);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失敗:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
double seconds = glfwGetTime();
uint64_t value = glfwGetTimerValue();
uint64_t freqency = glfwGetTimerFrequency();
printf("相對(duì)時(shí)間:%8.2f,真實(shí)時(shí)間:%lld,頻率:%lld\n", seconds, value, freqency);
glfwSetTime(0.0);
// 3. 設(shè)置清屏顏色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 釋放
glfwTerminate();
return 0;
}
// 編譯命令:g++ -omain gl09_timer.cpp -lglfw -lglew -framework opengl
