OpenGL(QT平台)学习与实战(一)
參考資料:
LearnOpenGL CN
《現代OpenGL:1入門篇,2021 Qt實現版》
OpenGL
我們先了解一下OpenGL到底是什么。一般它被認為是一個API(Application Programming Interface, 應用程序編程接口),包含了一系列可以操作圖形、圖像的函數。然而,OpenGL本身并不是一個API,它僅僅是一個由Khronos組織制定并維護的規范(Specification)。
OpenGL規范嚴格規定了每個函數該如何執行,以及它們的輸出值。至于內部具體每個函數是如何實現(Implement)的,將由OpenGL庫的開發者自行決定(注:這里開發者是指編寫OpenGL庫的人)。因為OpenGL規范并沒有規定實現的細節,具體的OpenGL庫允許使用不同的實現,只要其功能和結果與規范相匹配(亦即,作為用戶不會感受到功能上的差異)。
實際的OpenGL庫的開發者通常是顯卡的生產商。你購買的顯卡所支持的OpenGL版本都為這個系列的顯卡專門開發的。當你使用Apple系統的時候,OpenGL庫是由Apple自身維護的。在Linux下,有顯卡生產商提供的OpenGL庫,也有一些愛好者改編的版本。這也意味著任何時候OpenGL庫表現的行為與規范規定的不一致時,基本都是庫的開發者留下的bug。
所有版本的OpenGL規范文檔都被公開的寄存在Khronos那里。有興趣的讀者可以找到OpenGL3.3(我們將要使用的版本)的規范文檔。如果你想深入到OpenGL的細節(只關心函數功能的描述而不是函數的實現),這是個很好的選擇。如果你想知道每個函數具體的運作方式,這個規范也是一個很棒的參考。
狀態機
OpenGL自身是一個巨大的狀態機(State Machine):一系列的變量描述OpenGL此刻應當如何運行。OpenGL的狀態通常被稱為OpenGL上下文(Context)。我們通常使用如下途徑去更改OpenGL狀態:設置選項,操作緩沖。最后,我們使用當前OpenGL上下文來渲染。
假設當我們想告訴OpenGL去畫線段而不是三角形的時候,我們通過改變一些上下文變量來改變OpenGL狀態,從而告訴OpenGL如何去繪圖。一旦我們改變了OpenGL的狀態為繪制線段,下一個繪制命令就會畫出線段而不是三角形。
當使用OpenGL的時候,我們會遇到一些狀態設置函數(State-changing Function),這類函數將會改變上下文。以及狀態應用函數(State-using Function),這類函數會根據當前OpenGL的狀態執行一些操作。只要你記住OpenGL本質上是個大狀態機,就能更容易理解它的大部分特性。
對象
OpenGL庫是用C語言寫的,同時也支持多種語言的派生,但其內核仍是一個C庫。由于C的一些語言結構不易被翻譯到其它的高級語言,因此OpenGL開發的時候引入了一些抽象層。“對象(Object)”就是其中一個。
在OpenGL中一個對象是指一些選項的集合,它代表OpenGL狀態的一個子集。比如,我們可以用一個對象來代表繪圖窗口的設置,之后我們就可以設置它的大小、支持的顏色位數等等。可以把對象看做一個C風格的結構體(Struct):
struct object_name {GLfloat option1;GLuint option2;GLchar[] name; };基元類型(Primitive Type)
使用OpenGL時,建議使用OpenGL定義的基元類型。比如使用float時我們加上前綴GL(因此寫作GLfloat)。int、uint、char、bool等等也類似。OpenGL定義的這些GL基元類型的內存布局是與平臺無關的,而int等基元類型在不同操作系統上可能有不同的內存布局。使用GL基元類型可以保證你的程序在不同的平臺上工作一致。
當我們使用一個對象時,通常看起來像如下一樣(把OpenGL上下文看作一個大的結構體):
// OpenGL的狀態 struct OpenGL_Context {...object* object_Window_Target;... }; // 創建對象 GLuint objectId = 0; glGenObject(1, &objectId); // 綁定對象至上下文 glBindObject(GL_WINDOW_TARGET, objectId); // 設置當前綁定到 GL_WINDOW_TARGET 的對象的一些選項 glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH, 800); glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600); // 將上下文對象設回默認 glBindObject(GL_WINDOW_TARGET, 0);這一小段代碼展現了你以后使用OpenGL時常見的工作流。我們首先創建一個對象,然后用一個id保存它的引用(實際數據被儲存在后臺)。然后我們將對象綁定至上下文的目標位置(例子中窗口對象目標的位置被定義成GL_WINDOW_TARGET)。接下來我們設置窗口的選項。最后我們將目標位置的對象id設回0,解綁這個對象。設置的選項將被保存在objectId所引用的對象中,一旦我們重新綁定這個對象到GL_WINDOW_TARGET位置,這些選項就會重新生效。
使用對象的一個好處是在程序中,我們不止可以定義一個對象,并設置它們的選項,每個對象都可以是不同的設置。在我們執行一個使用OpenGL狀態的操作的時候,只需要綁定含有需要的設置的對象即可。比如說我們有一些作為3D模型數據(一棟房子或一個人物)的容器對象,在我們想繪制其中任何一個模型的時候,只需綁定一個包含對應模型數據的對象就可以了(當然,我們需要先創建并設置對象的選項)。擁有數個這樣的對象允許我們指定多個模型,在想畫其中任何一個的時候,直接將對應的對象綁定上去,便不需要再重復設置選項了。
QT簡介
QT是一套應用程序開發庫,但與MFC不同,QT是跨平臺的開發類庫。其中,跨平臺意味著只需要編寫一次程序,在不同平臺上無需改動或只需少許改動后再編譯,就可以形成在不同平臺上運行的版本。
使用QT的原因
優勢:
什么是第三方庫呢? ——GLFW+GLAD
GLFW解決操作系統層面的不同:
GLAD使得代碼可以用于不同的OpenGL驅動
總結
以上是生活随笔為你收集整理的OpenGL(QT平台)学习与实战(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MAC OS下编译tensorflow
- 下一篇: 应用启动失败,因为没有QT平台可以初始化