要想在OpenGL中繪圖,首先要創建一個窗口,後面的模型就繪製在這個窗口上。
1 導入庫
建立一個py文件,然後導出GLFW和GL的庫:
import glfw
from OpenGL.GL import *
2 初始化GLFW
若使用GLFW,則首先需要初始化GLFW:
if not glfw.init():
raise Exception("glfw can not be initialized!")
glfw.init()
函數用於初始化GLFW,在調用大部分其它GLFW函數前,都需要初始化GLFW。glfw.init()
如果成功,將會返回GLFW_TRUE,否則返回GLFW_FALSE,其中GLFW_TRUE和GLFW_FALSE是GLFW定義的常量,被定義爲於1和0。
若初始化失敗,則會輸出:glfw can not be initialized!
3 設置關於窗口的選項
使用glfw.window_hint()
函數設置hint
,這裏hint
可以理解爲一些關於窗口的選項。glfw.window_hint()
接受兩個參數,第一個是我們要設置的hint
的名字,使用GLFW常量
(以 glfw.
開頭)指定;第二個是我們要把該hint
設置成的值,該值隨要設置的hint
而異。
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) # OpenGL主版本號
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) # OpenGL副版本號
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) # OpenGL模式,此處設置爲OpenGL核心模式
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
# 4 MSAA is a good default with wide support
glfw.window_hint(glfw.SAMPLES, 4)
如上面所示,OpenGL版本號設置爲3.3
,OpenGL模式是核心模式。這樣的設置是有原因的具體後面再講。
4 創建窗口
glfw.create_window()
函數接受5個參數。第一個、第二個是窗口的寬和高,以像素爲單位,這裏分別是800和600(可根據顯示器設置);第三個是窗口標題,這裏是"My OpenGL window";第四個和第五個參數可以忽略,直接傳入None
。
創建完成之後要檢查一下是否創建完成。若創建失敗則輸出glfw window can not be created!
# creating the window
window = glfw.create_window(800, 600, "My OpenGL window", None, None)
# check if window was created
if not window:
glfw.terminate()
raise Exception("glfw window can not be created!")
然後查詢實際的framebuffer
大小,這樣我們可以稍後設置正確的viewport
# Query the actual framebuffer size so we can set the right viewport later
# -> glViewport(0, 0, framebuffer_size[0], framebuffer_size[1])
framebuffer_size = glfw.get_framebuffer_size(window)
最後設置窗口的位置(這裏是260,50),並且把創建的窗口設置成在當前線程上可使用的窗口,即接下來的畫圖都會畫在剛剛創建的窗口上。
# set window's position
glfw.set_window_pos(window, 260, 50)
# make the context current
# 讓當前窗口的環境在當前線程上成爲當前環境(接下來的畫圖都會畫在我們剛剛創建的窗口上)
glfw.make_context_current(window)
5 遊戲循環
和控制檯程序不同,我們希望這個程序可以一直運行,直到用戶關閉窗口(或有點擊鍵盤等)。這樣我們就需要創建一個循環,叫做遊戲循環(game loop)。
glfw.window_should_close()
檢查窗口是否需要關閉。如果是,遊戲循環就結束了,接下來我們將會清理資源,結束程序。
while not glfw.window_should_close(window):
glfw.poll_events()
glfw.swap_buffers(window)
glfw.swap_buffers( )
用來交換窗口的兩個顏色緩衝(color buffer)。這個概念叫做雙緩衝(double buffer)。如果不使用雙緩衝,就可能會出現閃屏現象,因爲繪製一般不是一下子就繪製完畢的,而是從左到右、從上到下地繪製。爲了避免這個問題,一般會使用雙緩衝,前緩衝(front buffer)是最終的圖像,而程序會在後緩衝(back buffer)上繪製。後緩衝繪製完畢後,就交換兩個緩衝,這樣就不會有閃屏的問題了。
glfw.poll_events()
用來檢查是否有事件被觸發,例如點擊關閉按鈕、點擊鼠標、按下鍵盤,等等。如果有,GLFW將會對這些事件進行處理。當某個事件觸發時,GLFW不會自動更新狀態,必須調用glfw.poll_events()
才能更新。調用glfw.poll_events()
時會檢查狀態是否有變化,如果有就會更新該狀態。如果設置了回調函數(這個將在以後講),還會調用相應的回調函數。如果不調用這個函數,不僅無法檢測輸入(後文會需要這樣),我們在點擊窗口右上角的X
時,GLFW也不會知道需要關閉窗口。所以必須在每一輪遊戲循環中調用這個函數。
最後,當循環執行完畢後,需要釋放前面所申請的資源
# terminate glfw, free up allocated resources
glfw.terminate()
glfw.terminate()
將會釋放所有GLFW資源,關閉當前窗口。然後程序就成功退出了。
6 完整代碼
import glfw
from OpenGL.GL import *
# initializing glfw library
if not glfw.init():
raise Exception("glfw can not be initialized!")
# Configure the OpenGL context.
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) # OpenGL主版本號
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) # OpenGL副版本號
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) # OpenGL模式,此處設置爲OpenGL核心模式
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
# 4 MSAA is a good default with wide support
glfw.window_hint(glfw.SAMPLES, 4)
# creating the window
window = glfw.create_window(800, 600, "My OpenGL window", None, None)
# check if window was created
if not window:
glfw.terminate()
raise Exception("glfw window can not be created!")
# Query the actual framebuffer size so we can set the right viewport later
# -> glViewport(0, 0, framebuffer_size[0], framebuffer_size[1])
framebuffer_size = glfw.get_framebuffer_size(window)
# set window's position
glfw.set_window_pos(window, 260, 50)
# make the context current
glfw.make_context_current(window)
# the main application loop
while not glfw.window_should_close(window):
glfw.poll_events()
glfw.swap_buffers(window)
# terminate glfw, free up allocated resources
glfw.terminate()
7 運行結果及改進
7.1 結果
運行程序可以看到一個黑色的窗口,如下所示:
7.2 改進
我們還可以設置背景色,比如設置成綠色。還可以改變退出控制方式,比如按下鍵盤q
就可以退出當前窗口。這個的代碼實現後面會補上。
150講輕鬆搞定Python網絡爬蟲