1. 程式人生 > >Tutorial 2:你好!點 (Hello dot! )

Tutorial 2:你好!點 (Hello dot! )

背景

這將是我們第一次接觸 GLEW(OpenGL Extension Wrangler Library)。GLEW能幫助管理OpenGL的擴充套件庫。當你初始化完它之後,它將在你的系統上將尋找所有可用的擴充套件功能,動態的載入它們,並通過一個單一的標頭檔案提供簡單的介面。

在這一節教程中,我們將第一次看見頂點緩衝區物件(Vertex Buffer Objects)的用例。顧名思義,它們是被用來儲存頂點物件的。在3D世界中你想具象化的物件,無論是怪物,城堡或一個簡單的旋轉立方體,總是由連線在一起的一組頂點構建而成的。VBOs是載入頂點進入 GPU 最高效的方法。VBOs是可以儲存在視訊記憶體中的緩衝區這使得VBOs有最短的時間去進入GPU,所以這個方法也是被推薦的。

這一節和下一節教程的內容在本系列教程中是唯一講述固定管線而不是可程式設計管線的部分,事實上這兩節內容中我們也不會用到任何變換,我們僅僅是讓將資料傳遞給管線而已。在接下來的學習中我們將完整學習渲染管線,但是現在,在涉及到光柵器之前我們使用螢幕座標系繪製點、線、和三角形,點的座標用X,Y,Z表示並且他們的值都在[-1.0, 1.0]之間。光柵器將這些座標對映到螢幕空間(比如,如果螢幕的寬度是1024,X 的座標為-1.0,則 X 將對映到0;若 X 座標為1.0,則將會被將對映到1023)。最後,光柵器根據指定繪圖命令(可以在下面的原始碼解析中看到)的拓撲結構畫出圖元。因為我們沒有繫結任何shader到管線中,所有頂點沒有進行矩陣變化。這將意味著為了在螢幕中繪製出這些點我們僅僅需要傳遞給程式一些在上述範圍之內的值就可以了。事實上,我們選取在螢幕中的零點作為x、y兩條軸的中心點,換句話說,零點是在螢幕的正中心。

GLEW安裝: 從伺服器 http://glew.sourceforge.net/中可以獲得。大部分 Linux 為 GLEW 提供了預編譯包。在 Ubuntu 上,你可以安裝通過執行下面的命令列命令 apt-get install libglew1.6 libglew1.6-dev 來安裝它。

程式碼詳解

#define GLEW_STATIC
#include<GL/glew.h>

這裡我們包含了一個單一的 GLEW 標頭檔案。如果你包含其他 OpenGL 標頭檔案,你必須把 GLEW 標頭檔案放在其他標頭檔案之前。

include “math_3d.h”

在這一節我們開始使用其他的一些輔助結構比如 vector。我們以後將會擴充套件這個標頭檔案。

GLenum res =glewInit();
if (res != GLEW_OK)
{
   fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
   return 1;
}

這裡我們初始化 GLEW 和檢查是否存在一些錯誤。這必須要在 GLUT 被初始化之前完成。

Vector3f Vertices[1];
Vertices[0] =Vector3f(0.0f, 0.0f, 0.0f);

我們建立了一個型別為 Vector3f(這個型別被定義在 math_3d.h)的陣列,同時初始化 X、Y、Z為0.這將會使我們繪製的點出現在螢幕中間。

GLuint VBO;

我們分配一個全域性變數 GLuint 儲存頂點快取區物件的控制代碼,你稍後將看到大部分 OpenGL 物件都是通過一個 GLuint 型別的變數來訪問的。

glGenBuffers(1,&VBO);

OpenGL為了生成不同型別的物件定義幾個 glGen* 函式。這些函式通常有兩個引數,第一個引數指定你想要建立物件的數量,第二個引數是一個存放 GLuint 型別陣列的地址,這個陣列用於存放函式生成的控制代碼(確定陣列是足夠大來存放你的所申請的緩衝區控制代碼)。以後呼叫這個函式將不會生成相同的控制代碼,除非你使用 glDeleteBuffers 函式刪除它。在這個地方,你不需要指定用這些 buffers 用於做什麼,所以建立的是普通的 buffers,指定這個 buffer 的功能是下面一個函式的任務

glBindBuffer(GL_ARRAY_BUFFER,VBO);

OpenGL 有一個獨一無二的方法使用控制代碼。在許多的 API 中,控制代碼只是簡單的通過一些相關的函式來使用。在 OpenGL 中我們繫結控制代碼到到一個目標上,然後在目標上執行命令。這些命令的執行隻影響到已經繫結的控制代碼,直到當前控制代碼被代替或者將0繫結到目標上。目標 GL_ARRAY_BUFFER 表示緩衝區用於儲存頂點陣列。另一個有用的目標是 GL_ELEMENT_ARRAY_BUFFER 表示緩衝區用於儲存陣列的索引。我們也可以將控制代碼繫結到別的目標上,我們將在下一節看到。

glBufferData(GL_ARRAY_BUFFER,sizeof(Vertices),Vertices,GL_STATIC_DRA);

當我們將緩衝區繫結到目標上之後,我們需要用資料進行填充。上面函式的引數包括:目標點名稱(和上面緩衝區繫結的目標點一樣),資料的位元組數,頂點陣列的地址,以及一個表示資料使用方式的列舉量。因為我們不需要改變緩衝區中的內容,所謂我們將資料指定為 GL_STATIC_DRAW,與之相反的我們可以將其設定為 GL_DYNAMIC_DRAW。通過設定這個值,OpenGL可以對資料進行一些優化(比如在記憶體中哪個地方最適合儲存緩衝區)。

glEnableVertexAttribArray(0);

在 shaders 章節中,你將看見 Shader 中用到的頂點屬性(位置,法線等)有一個對映到它們的索引,使我們在 C/C++ 專案中建立的資料能與 Shader 內的屬性名之間進行繫結。此外你必須啟用每個頂點屬性的索引。在這一節中我們還沒使用任何 Shader,但是我們載入到緩衝器的頂點位置屬性在固定函式管線(在沒有繫結著色器的時候就自動啟用固定管線)中被看做頂點屬性索引為0。你必須啟用所有的頂點屬性,否則管線將接收不到資料。

glBindBuffer(GL_ARRAY_BUFFER,VBO);

由於將要呼叫繪圖函式,所以這裡我們再一次綁定了緩衝區。在這個小的專案中我們只有一個頂點緩衝區,所以在每一幀都呼叫這個函式是多餘的。但是在更復雜的專案中可能存在很多個緩衝區來儲存不同型別的變數,所以你必須用你打算使用的緩衝區來更新渲染管線狀態。

glVertexAttribPointer(0,3, GL_FLOAT, GL_FALSE, 0, 0);

這個函式呼叫告訴管線如何在緩衝區內部解釋資料。第一個引數指定了屬性的索引。我們都知道0是預設的,但是當我們開始使用 Shaders 的時候,我們在 Shader 中需要明確的設定索引。第二個引數是構成屬性的分量的個數(X,Y,Z共三個分量)。第三個引數是每個分量的資料型別。第四個引數表明屬性在管線中使用之前是否需要被規範化。第五個引數是在緩衝區中兩個相同屬性值之間的間隔的位元組數,當只有一個屬性時(比如緩衝區只包含頂點位置)並且資料是緊挨著的,那麼我們設定這個值為0。如果我們有一個包含位置屬性和法線屬性的陣列(每個屬性都是一個float型別的三維向量),我們將這個值設定為6*4=24。最後一個引數在上一個例子中是有用的。我們需要指定在緩衝區中儲存資料的偏移值,這樣管線才會找到資料。當頂點的位置和法線相鄰儲存時時,我們設定頂點位置的偏移值為0而頂點法線的偏移值為12。

glDrawArrays(GL_POINTS,0, 1);

最後,呼叫這個函式來畫幾何體。這裡就是 GPU 真正開始工作的地方。它現在將結合繪圖命令的引數,然後建立一個點並將結果渲染到螢幕。

OpenGL 提供多個型別的渲染命令,每一個都適合於不同的情況。通常你可以把它們分成兩個個類別——有序渲染和索引渲染。有序渲染相對來說比較簡單。GPU 遍歷你的頂點緩衝區,一個接著一個的訪問頂點,然後根據在函式中指定的引數類別解釋資料,例如,如果你指定 GL_TRIANGLES,那麼頂點0-2成為第一個三角形,3-5是第二個三角形等。如果你想讓相同的頂點出現在不同的三角形中,你將需要在頂點緩衝區指定它兩次,但是這樣將會浪費空間。

使用索引渲染相對來說複雜一點,並且涉及到了一個額外的緩衝區——索引緩衝區。索引緩衝區存放的是頂點在頂點緩衝區中的索引值。GPU 遍歷索引緩衝區,與順序渲染類似,他會將索引為0-2描述為第一個三角形。如果你想要相同的頂點在兩個三角形中,那麼只需要在索引緩衝區中簡單的指定該頂點的索引兩次,頂點緩衝區僅僅只需要包含一份資料。索引緩衝區在遊戲使用的更加普遍,因為大部分模型的表面(人的面板,城堡的牆等等)都是由共享頂點的三角形組成的。

在這一節中,我們使用最簡單的繪圖命令——glDrawArrays。這是一個已經順序繪製命令,所以這裡沒有儲存索引緩衝區。我們指定點的拓撲結構為 GL_POINTS ,這意味著頂點緩衝區中的每一個頂點都被繪製成一個點。下一個引數是開始繪製的第一個頂點的索引值。因為我們想要從緩衝區的開始來繪圖,所以我們指定引數為0。這使我們可以在相同的緩衝區儲存多個模型,在繪製圖形的時候只需要只需要選擇不同的偏移量就行了。最後一個引數是要用於繪製的頂點的數量。

glDisableVertexAttribArray(0);

當頂點不是要立即被使用的時候,禁用所有的頂點屬性是一個很不錯的方法。當著色器不使用頂點的時候將頂點屬性啟用,這是給自己自找麻煩。

相關推薦

Tutorial 2:你好 (Hello dot! )

背景 這將是我們第一次接觸 GLEW(OpenGL Extension Wrangler Library)。GLEW能幫助管理OpenGL的擴充套件庫。當你初始化完它之後,它將在你的系統上將尋找所有可用的擴充套件功能,動態的載入它們,並通過一個單一的標頭檔案提

在imageView依次加入7個手勢, 1.擊哪個button,往imageView上加入哪個手勢.(保證視圖上僅僅有一個手勢). 2.輕拍:擊視圖切換美女圖片.(imageView上首先展示的美女

rac info clas -a 點擊事件 hone sms down dispose // // ControlView.h // HomeworkGestureRecognizer // // Created by lanouhn on 14-8-27. //

你好

先來 con word 網站 noip blank www pen noi 嘿,先來介紹我的主頁吧! 我的主頁會發布一些我在學習編程過程中的筆記。主要包括 NOIp 系列考試往年真題,和我正在利用來自學的網站:計蒜客上的一些題目。 希望我的一些錯誤能給你提醒,也希望我的思

2017再見~2018你好

相對 電話 幫助 網站 業務 銀行卡 每天 時報 火車站 今天是2017-12-27,最近新版本發布,這2天相對有點閑了,忽然想著要不要總結記錄下點什麽呢~ 依稀還記得16年的最後一個工作日12.30號加班到快12點才回家~時間真的過得好塊~再過幾天就是2018了~ 說說我

centos7.2 搭建單clusterFS分布式存儲

查看 mkfs.xfs port glusterfs inux 兩臺 啟動服務 服務器 客戶 環境兩臺服務器192.168.10.17192.168.10.26客戶端192.168.10.27 關閉selinux和firewalld 確保var目錄的空間最少為200M

深入理解計算機系統 2.4.2 IEEE浮表示詳細講解

定義 IEEE浮點標準用以下公式表示\(V = (-1)^s * M * 2^E\) 符號(sign):s決定這書是負數(s = 1)還是正數(s = 0),而對於數值0的符號位解釋作為特殊情況處理 。 尾數(significand):M是一個二進位制小數,它的範圍是\

IGFrame版本釋出更新相關下載【Ver0.2釋出近期將補全使用教程】

感興趣或者有疑問的各位可以留言或加Q群210816248~驗證:IGFrame IGFrame Ver0.3預告(JavaSE版本+Android移植版) =================================================================

配置mpvue的less,只需2

  第1步:下載less到專案中 執行 npm install less less-loader --save   第2步:配置webpack.base.conf.js 在module->rules中加入 { test: /\.les

2-2 韓信

相傳韓信才智過人,從不直接清點自己軍隊的人數,只要讓士兵先後以三人一排、五人一排、七人一排地變換隊形,而他每次只掠一眼隊伍的排尾就知道總人數了。輸入包含多組資料,每組資料包含3個非負整數a,b,c,表示每種隊形排尾的人數(a<3,b<5,c<7),輸出總人數的最小值(或報告

Docker 建立 Crowd3.3.2 以及打通 Jira Software7.12.3和Confluence6.12.2 SSO 單登入

目錄 目錄 1、介紹 1.1、什麼是Crowd? 2、Crowd 的官網在哪裡? 3、如何下載安裝? 4、對 Crowd 進行配置 4.1、破解 Crowd 第一步 4.2、破解 Crowd 第二步,獲取授權許可 4.2、Crowd

向大牛學習2.0

int test(int n) {      n = (n&0x55555555) + ((n>>1)&0x55555555);      n = (

jzxx1570 1!+2!+3+……+N

題目描述 用高精度計算出S=1!+2!+3!+…+n!(n≤50) 其中“!”表示階乘,例如:5!=54321。 輸入 一行,一個正整數N。 輸出 一行,一個正整數,即結果S。 樣例輸入 5 樣例輸出 153 滿分程式碼: #include<stdio

2-2 韓信

相傳韓信才智過人,從不直接清點自己軍隊的人數,只要讓士兵先後以三人一排、五人一排、七人一排地變換隊形,而他每次只掠一眼隊伍的排尾就知道總人數了。輸入包含多組資料,每組資料包含3個非負整數a,b,c,表示每種隊形排尾的人數(a<3,b<5,c<7

Android RoboGuice 使用指南 2 第一個例子Hello World

                首先介紹一下如果將Guice 和RoboGuice 的庫新增到專案中。建立一個新Android專案,比如GuiceDemo,目標平臺Android1.5以上。一般可以在該專案下新增一個lib目錄,將兩個jar檔案拷到lib目錄下,然後通過: Project > Prope

洛谷2944 地震損失2Earthquake Damage 2 (刪最小割)

題目連結 感覺比較好的一道題啊 qwq 首先,如果我們讓 S 和 1

Codeforces Round #339 (Div. 2)-C(到線段的最短距離)

Peter got a new snow blower as a New Year present. Of course, Peter decided to try it immediately. After reading the instructions he realized that it doe

世界,你好喬遷之喜

2015-05-17 2015.5.17日正式從美國hostmonster遷入香港。感謝mt提供主機。 本部落格幾經輾轉。先是2006年在godaddy申請域名和空間,後面轉dreamhost, bluehost,hostmo

jzxx1570 1!+2!+3+……+N

題目描述 用高精度計算出S=1!+2!+3!+…+n!(n≤50) 其中“!”表示階乘,例如:5!=54321。 輸入 一行,一個正整數N。 輸出 一行,一個正整數,即結果S。 樣例輸入 5 樣例輸出 153 滿分程式碼: #include<stdio.h

譯-PHP rabbitMQ Tutorial-2

Work Queues (工作/任務佇列) In the first tutorial we wrote programs to send and receive messages from a named queue. In this one we'll cr

基於js和openlayer計算2個經緯度之間的距離

基於js和openlayer計算2個經緯度點之間的距離 //計算2個經緯度點之間的距離 //Haversine formula 演算法 var harvensin=function() { this.earch_radius=6371008.8; // 地球半徑 平均值 米