一、基礎(chǔ)管線
OpenGL 中圖元只不過是頂點(diǎn)的集合以預(yù)定義的方式結(jié)合在一起。
管線分為2個部分:上半部分是客戶機(jī)端,下半部分是服務(wù)器端。
服務(wù)器和客戶端是功能和運(yùn)行上都是異步的,它們是各自獨(dú)立的軟件或硬件塊。

- 客戶端是存儲在 CPU 存儲器中的,并且在應(yīng)用程序中執(zhí)行,或者在主系統(tǒng)內(nèi)存的驅(qū)動程序中執(zhí)行。驅(qū)動程序會將渲染命令和數(shù)組組合起來,發(fā)送給服務(wù)器執(zhí)行?。ㄔ谝慌_典型的個人計(jì)算機(jī)上,服務(wù)器實(shí)際上就是圖形加速卡上的硬件和內(nèi)存)
- 服務(wù)器和客戶機(jī)在功能上也是異步的。它們是各自獨(dú)立的軟件塊或硬件塊。我們是希望它們2個端都盡量在不停的工作??蛻舳瞬粩嗟陌褦?shù)據(jù)塊和命令塊組合在一起輸送到緩沖區(qū),然后緩沖區(qū)就會發(fā)送到服務(wù)器執(zhí)行。
- 如果服務(wù)器停止工作等待客戶機(jī),或者客戶機(jī)停止工作來等待服務(wù)器做好接受更多的命令和準(zhǔn)備,我們把這種情況稱為管線停滯
二、著色器
渲染過程,必備的2個著色器“頂點(diǎn)著色器”和“片元著色器”。
上圖的Vertex Shader(頂點(diǎn)著?色器器) 和 Fragment Shader(?片段著?色器器)。
- 著?器是使?GLSL編寫的程序,看起來與C語?非常類似。著?器必須從源代碼中編譯和鏈 接在?起。最終準(zhǔn)備就緒的著色器程序
- 頂點(diǎn)著?器-->處理從客戶機(jī)輸?的數(shù)據(jù)、應(yīng)?變換、進(jìn)?其他的類型的數(shù)學(xué)運(yùn)算來計(jì)算光照效果、位移、顏?色值等等。(**為了渲染共有3個頂點(diǎn)的三角形,頂點(diǎn)著?器將執(zhí)?3次,也就是為了每個頂點(diǎn)執(zhí)行?次)在?前的硬件上有多個執(zhí)行單元同時運(yùn)行,就意味著所有的3個頂點(diǎn)可以同時進(jìn)行處理!
- 圖上(primitive Assembly)說明的是:3個頂點(diǎn)已經(jīng)組合在一起,而三角形已經(jīng)逐個片段的進(jìn)行了光柵化。每個片段通過執(zhí)行 片元著色器 進(jìn)行填充。片元著色器會輸出我們將屏幕上看到的最終顏色值。
三、3種向 OpenGL 著色器傳遞渲染數(shù)據(jù)的方法
- 屬性
- Uniform
- 紋理
3.1 屬性
屬性:就是對一個頂點(diǎn)都要作改變的數(shù)據(jù)元素。實(shí)際上,頂點(diǎn)位置本身就是一個屬性。屬性就可以浮點(diǎn)類型、整形、布爾類型。
- 屬性總是以四維向量的形勢進(jìn)行內(nèi)部存儲的,即使我們不會使用所有的4個分量。一個頂點(diǎn)位置可能存儲 (x,y,z),將占有4個分量中的3個。
- 實(shí)際上如果是在平面情況下:只要在 xy 平面上就能繪制,那么z分量就自動設(shè)置為0。
- 屬性還可以是:紋理坐標(biāo)、顏色值、光照計(jì)算表面法線
- 在頂點(diǎn)程序 (shader渲染)可以代表你想要的任何意義。因?yàn)槎际悄阍O(shè)定的。
- 屬性會從本地客戶機(jī)內(nèi)存中復(fù)制在圖形硬件中的一個緩沖區(qū)上。這些屬性只提供給頂點(diǎn)著色器使用,對于片元著色器沒有太大意義。
- 聲明 這些屬性對每個頂點(diǎn)都要作改變,但并不意味著它們的值不能重復(fù)。通常情況下,它們都是不一樣的,但有可能整個數(shù)組都是同一值的情況。
3.2 Uniform 值
通過設(shè)置 Uniform 變量就緊接著發(fā)送一個圖元批次命令。Uniform 變量實(shí)際上可以無限地使用,設(shè)置一個應(yīng)用于整個表面的單個顏色值。還可以設(shè)置一個時間值。在每次渲染某種類型的頂點(diǎn)動畫時修改它。
- 注意 這里的 uniform 變量每個批次改變一次,而不是每個頂點(diǎn)改變一次。
- uniform 變量最常見的應(yīng)用是在頂點(diǎn)渲染中設(shè)置變換矩陣
- 與屬性相同點(diǎn):可以是浮點(diǎn)型、整數(shù)、布爾值
- 與屬性不同點(diǎn):頂點(diǎn)著色器和片元著色器都可以使用 uniform 變量。uniform 變量還可以是標(biāo)量類型、矢量類型、uniform 矩陣。
3.3 紋理
簡單的說,紋理就是矩形的數(shù)據(jù)數(shù)組。例如顏色、亮度數(shù)據(jù)等,之所以復(fù)雜,是因?yàn)榫匦渭y理可以映射到非矩形的區(qū)域。
四、創(chuàng)建坐標(biāo)系
GLFrustum frustum;
void SetOrthographic(GLfloat xMin, GLfloat xMax, GLfloat yMin, GLfloat yMax, GLfloat zMin, GLfloat zMax);
五、透視投影
GLFrustum frustum;
void SetPerspective(float fFov, float fAspect, float fNear, float fFar);

透視投影會進(jìn)行透視除法對距離觀察者很遠(yuǎn)的對象進(jìn)行縮放和收縮。在投影到屏幕之后,視景體背面與視景體正面的寬度測量標(biāo)準(zhǔn)不同。
上圖所示: 平頭截體(frustum)的幾何體,它的觀察方向是從金字塔的尖端到寬闊端。觀察者的視點(diǎn)與金字塔的尖端拉開一定距離。
GLFrustum類通過setPerspective ?方法為我們構(gòu)建?一個平截頭體。
參數(shù):
fFov:垂直?方向上的視場?角度
fAspect:窗?口的寬度與?高度的縱橫?比
fNear:近裁剪?面距離
fFar:遠(yuǎn)裁剪?面距離
縱橫?比 = 寬(w)/?高(h)
CLFrustum::SetPerspective(float fFov,float fAspect,float fNear
,float fFar);
六、存儲著色器
6.1 GLShaderManager 的初始化
GLShaderManager shaderManager;
shaderManager.InitializeStockShaders();
shaderManager.UseStockShader(參數(shù)列表) // 使用
6.2 GLShaderManager 屬性
| 標(biāo)識符 | 描述符 |
|---|---|
GLT_ATTRIBUTE_VERTEX |
3分量(x,y,z)頂點(diǎn)位置 |
GLT_ATTRIBUTE_COLOR |
4分量(r,g,b,a)顏色值 |
GLT_ATTRIBUTE_NORMAL |
3分量(x,y,z)表面法線 |
GLT_ATTRIBUTE_TEXTUREO |
第一對2分量(s,t)紋理坐標(biāo) |
GLT_ATTRIBUTE_TEXTURE1 |
第二對2分量(s,t)紋理坐標(biāo) |
存儲著色器為每一個變量都使用一致的內(nèi)部變量命名規(guī)則和相同的屬性槽。
6.3 GLShaderManager 的 uniform 值
- 一般情況,要對幾何圖形進(jìn)行渲染,我們需要給對象遞交屬性矩陣,首先要綁定我們要使用的著色程序上,并提供程序的 uniform 值。但是 GLShanderManager 類可以暫時為我們完成工作。
- useStockShader 函數(shù)會選擇一個存儲著色器并提供這個著色器的 unifrom 值。
GLShaderManager::UserStockShader(GLeunm shader ...);
-
單位著色器 只是簡單地使用默認(rèn)笛卡爾坐標(biāo)系(坐標(biāo)范圍(-1.0,1.0))。所有的片段都應(yīng)用同一種顏色,幾何圖形為實(shí)心和為渲染的。 需要這種存儲著色器一個屬性:
GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)vColor[4] 需要的顏色GLShaderManager::UserStockShader(GLT_ATTRIBUTE_VERTEX,GLfloat vColor[4]); -
平面著色器 它將統(tǒng)一著色器進(jìn)行拓展。允許為幾何圖形變換指定一個 4*4 變換矩陣。經(jīng)常被統(tǒng)稱為“模型視圖投影矩陣”
參數(shù)1:平面著色器
參數(shù)2:允許變化的 4*4 矩陣GLShaderManager::UserStockShader(GLT_ATTRIBUTE_VERTEX,GLfloat vColor[4]); -
上色著色器 在幾何圖形中應(yīng)用的變換矩陣。需要設(shè)置存儲著色器的
GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量) 和GLT_ATTRIBUTE_COLOR(顏色分量)2個屬性。顏色值將被平滑地插入頂點(diǎn)之間(平滑著色)GLShaderManager::UserStockShader(GLT_SHADER_SHADED,GLfloat mvp[16]); -
默認(rèn)光源著色器 這種著色器,是對象產(chǎn)生陰影的光照效果。需要設(shè)置存儲著色器的
GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)和GLT_ATTRIBUTE_NORMAL(表面法線)
參數(shù)1:默認(rèn)光源著色器
參數(shù)2:模型視圖矩陣
參數(shù)3:投影矩陣
參數(shù)4:顏色值GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vColor[4]); -
點(diǎn)光源著色器 點(diǎn)光源著色器和默認(rèn)光源著色器很相似,區(qū)別在于,光源位置是特定的。同樣需要設(shè)置存儲著色器的
GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)和GLT_ATTRIBUTE_NORMAL(表面法線)
參數(shù)1:點(diǎn)光源著色器
參數(shù)2:模型視圖矩陣
參數(shù)3:投影矩陣
參數(shù)4:視點(diǎn)坐標(biāo)光源位置
參數(shù)5:顏色值GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT_DIEF,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vColor[4]); -
紋理替換矩陣 著色器通過給定的模型視圖投影矩陣,使用綁定到
nTextureUnit(紋理單元)指定紋理單元的紋理對幾何圖形進(jìn)行變化。
片段顏色:是直接從紋理樣本中直接獲取的。
需要設(shè)置存儲著色器的GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)和GLT_ATTRIBUTE_NORMAL(表面法 線)GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_REPLACE,GLfloat mvMatrix[16],GLintnTextureUnit); -
紋理調(diào)整著色器 將紋理調(diào)整著色器乘以一個取自紋理單元
nTextureUnit的紋理。需要設(shè)置存儲著色器的GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)和GLT_ATTRIBUTE_TEXTURE0(紋理坐標(biāo))GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_MODULATE,GLfloat mvMatrix[16],GLfloat vColor[4],GLint nTextureUnit); -
紋理光源著色器 將一個紋理通過漫反射照明計(jì)算機(jī)進(jìn)行調(diào)整(相乘)。光線在視覺空間中的位置是給定的。需要設(shè)置存儲著色器的
GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)和GLT_ATTRIBUTE_TEXTURE0(紋理坐標(biāo))、GLT_ATTRIBUTE_NORMAL(表面法線)
參數(shù)1:紋理光源著色器
參數(shù)2:投影矩陣
參數(shù)3:視覺空間中的光源位置
參數(shù)4:幾何圖形的基本色
參數(shù)5:將要使用的紋理單元GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_MODULATE,GLfloat mvMatrix[16],GLfloat vColor[4],GLint nTextureUnit);
七、OpenGL 圖元
點(diǎn)、線、線帶、線環(huán)、三角形、三角形金字塔、三角形帶、三角形扇
//修改點(diǎn)的大小
glPointSize(4.0f);
//設(shè)置點(diǎn)的大小范圍,點(diǎn)和點(diǎn)之間的距離
GLfloat sizes[2] = {2.0f,4.0f};
GLfloat stepSize = 1.0f;
//獲取點(diǎn)的大小范圍和步長
glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
glGetFloatv(GL_POINT_GRAULRITY,&stepSize);
//3.通過使用程序點(diǎn)大小模式設(shè)置點(diǎn)大小
glEnable(GL_PROGAM_POINT_SIZE);
//GLSL程序
gl_PointSize = 5.0f;
八、GLBatch 容器(幫助類)
void GLBatch::Begin(GLenum primitive, GLuint nVerts, GLuint nTextureUnits = 0);
void GLBatch::CopyNormalDataf(M3DVector3f *vNorms);
void GLBatch::CopyColorData4f(M3DVector4f *vColors);
void GLBatch::CopyTexCoordData2f(M3DVector2f *vTexCoords, GLuint uiTextureLayer);
