原創(chuàng):知識(shí)探索型文章
創(chuàng)作不易,請(qǐng)珍惜,之后會(huì)持續(xù)更新,不斷完善
個(gè)人比較喜歡做筆記和寫(xiě)總結(jié),畢竟好記性不如爛筆頭哈哈,這些文章記錄了我的IOS成長(zhǎng)歷程,希望能與大家一起進(jìn)步
溫馨提示:由于簡(jiǎn)書(shū)不支持目錄跳轉(zhuǎn),大家可通過(guò)command + F 輸入目錄標(biāo)題后迅速尋找到你所需要的內(nèi)容
目錄
- 一、OpenGL變化
- 1、3D數(shù)學(xué)
- 2、仿射變換
- 二、繪制圖形
- 1、繪制球體
- 2、繪制其他圖形
- 3、繪制自動(dòng)旋轉(zhuǎn)的球體
- 4、繪制圍繞太陽(yáng)旋轉(zhuǎn)的地球
- 三、OpenGL紋理
- 1、繪制金字塔
- 2、繪制隧道
- 3、繪制自動(dòng)旋轉(zhuǎn)的球體世界
- Demo
- 參考文獻(xiàn)
續(xù)文見(jiàn)上篇:iOS多媒體:OpenGL(上)
一、OpenGL變化
1、3D數(shù)學(xué)
a、3D數(shù)學(xué)的介紹
GITools庫(kù)中有一個(gè)組件叫Math3d,其中包含了大量好用的OpenGL的3D數(shù)學(xué)類(lèi)型。雖然我們不必親自進(jìn)行所有的矩陣和向量的操作,但我們需要知道它們是什么以及如何運(yùn)用它們。AR Kit框架以及Unity3D、游戲開(kāi)發(fā)都必須學(xué)習(xí)3D數(shù)學(xué)知識(shí)。
在開(kāi)發(fā)過(guò)程中,我們涉及到的圖形變換,就會(huì)涉及到矩陣/向量的計(jì)算。例如大家在使用CAnimation實(shí)現(xiàn)仿射變換時(shí)就使用了OpenGL渲染技術(shù)。圖形的各個(gè)頂點(diǎn)*統(tǒng)一的變換矩陣就可以進(jìn)行平移、旋轉(zhuǎn)、縮放。
// 旋轉(zhuǎn)
void MatrixStack::Rotate(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);// angle參數(shù)傳遞的度數(shù),?不是弧度
// 平移
void MatrixStack::Translate(GLfloat x,GLfloat y,GLfloat z);
// 縮放
void MatrixStack::Scale(GLfloat x,GLfloat y,GLfloat z);
b、OpenGL math3d庫(kù)
math3d庫(kù)有2個(gè)數(shù)據(jù)類(lèi)型,能夠表示?個(gè)三維或者四維向量。M3DVector3f可以表示?個(gè)三維向量(x,y,z),而M3DVector4f則可以表示一個(gè)四維向量(x,y,z,w)。在典型情況下,w 坐標(biāo)設(shè)為1.0。x,y,z值通過(guò)除以w來(lái)進(jìn)?行行縮放。除以1.0本質(zhì)上不改變x,y,z值。
// 聲明?個(gè)三維向量頂點(diǎn)數(shù)組,例如生成一個(gè)三角形
M3DVector3f vVerts[] = {
-0.5f,0.0f,0.0f,
0.5f,0.0f,0.0f,
0.0f,0.5f,0.0f
};
c、實(shí)現(xiàn)向量計(jì)算的方法
點(diǎn)乘
返回的是-1,1之間的值,代表這2個(gè)向量的余弦值
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
返回2個(gè)向量之間的弧度值
float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);
叉乘
叉乘運(yùn)算結(jié)果返回?個(gè)新的向量,這個(gè)新的向量與原來(lái)的2個(gè)向量垂直
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
d、圖形的變化過(guò)程
- 視圖:指定觀察者位置
- 模型:在場(chǎng)景中移動(dòng)物體
- 模型視圖:描述視圖/模型變換的?元性
- 投影:改變視景體?小和設(shè)置它的投影?式
- 視口:偽變化,對(duì)窗口上最終輸出進(jìn)行縮放

2、仿射變換

a、使用到的屬性
在x、y軸上移動(dòng)的距離
GLfloat xPos = 0.0f;
GLfloat yPos = 0.0f;
b、實(shí)現(xiàn)移動(dòng)的方法
void SpecialKeys(int key, int x, int y)
{
}
移動(dòng)的步長(zhǎng)
GLfloat stepSize = 0.025f;
上下左右移動(dòng)
if(key == GLUT_KEY_UP) yPos += stepSize;
if(key == GLUT_KEY_DOWN) yPos -= stepSize;
if(key == GLUT_KEY_LEFT) xPos -= stepSize;
if(key == GLUT_KEY_RIGHT) xPos += stepSize;
檢測(cè)是否碰撞邊界
if(xPos < (-1.0f + blockSize)) xPos = -1.0f + blockSize;
if(xPos > (1.0f - blockSize)) xPos = 1.0f - blockSize;
if(yPos < (-1.0f + blockSize)) yPos = -1.0f + blockSize;
if(yPos > (1.0f - blockSize)) yPos = 1.0f - blockSize;
重新渲染
glutPostRedisplay();
c、實(shí)現(xiàn)渲染場(chǎng)景的方法
void RenderScene(void)
{
}
平移、旋轉(zhuǎn)、最終矩陣
M3DMatrix44f mFinalTransform, mTranslationMatrix, mRotationMatrix;
根據(jù)xPos,yPos進(jìn)行平移,每一個(gè)頂點(diǎn)都乘以平移矩陣
m3dTranslationMatrix44(mTranslationMatrix, xPos, yPos, 0.0f);
每次重繪時(shí),旋轉(zhuǎn)5度
static float yRot = 0.0f;
yRot += 5.0f;
m3dRotationMatrix44(mRotationMatrix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
將旋轉(zhuǎn)和移動(dòng)的結(jié)果合并到mFinalTransform中(矩陣叉乘)
m3dMatrixMultiply44(mFinalTransform, mTranslationMatrix, mRotationMatrix);
將矩陣結(jié)果提交到固定著色器(平面著色器)中
shaderManager.UseStockShader(GLT_SHADER_FLAT, mFinalTransform, vRed);
squareBatch.Draw();
執(zhí)行緩沖區(qū)交換
glutSwapBuffers();
二、繪制圖形
1、繪制球體

a、使用到的屬性
// 觀察者位置
GLFrame cameraFrame;
// 世界坐標(biāo)位置
GLFrame objectFrame;
// 視景體,用來(lái)構(gòu)造投影矩陣
GLFrustum viewFrustum;
// 三角形批次類(lèi)
GLTriangleBatch CC_Triangle;
// 球
GLTriangleBatch sphereBatch;
// 環(huán)
GLTriangleBatch torusBatch;
// 圓柱
GLTriangleBatch cylinderBatch;
// 錐
GLTriangleBatch coneBatch;
// 磁盤(pán)
GLTriangleBatch diskBatch;
b、上下左右,移動(dòng)圖形
移動(dòng)世界坐標(biāo)系,而不是去移動(dòng)物體。比如將世界坐標(biāo)系在X方向移動(dòng)-5.0。
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP) objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
if(key == GLUT_KEY_DOWN) objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
if(key == GLUT_KEY_LEFT) objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
if(key == GLUT_KEY_RIGHT) objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
glutPostRedisplay();
}
c、添加數(shù)據(jù)源
void SetupRC()
{
}
開(kāi)啟深度測(cè)試(立體)
glEnable(GL_DEPTH_TEST);
表示觀察者離屏幕之間的距離,若是負(fù)數(shù),是往屏幕后面移動(dòng);若是正數(shù),往屏幕前面移動(dòng)。將觀察者坐標(biāo)位置Z往屏幕里移動(dòng)15個(gè)單位位置。
cameraFrame.MoveForward(-15.0f);
或者將物體向屏幕外移動(dòng)15.0
objectFrame.MoveForward(15.0f);
利用三角形批次類(lèi)構(gòu)造圖形對(duì)象——球
- sphereBatch:三角形批次類(lèi)對(duì)象
- fRadius:球體半徑
- iSlices:從球體底部堆疊到頂部的三角形帶的數(shù)量,其實(shí)球體是一圈一圈三角形帶組成
- iStacks:圍繞球體一圈排列的三角形對(duì)數(shù)
- 一個(gè)對(duì)稱(chēng)性較好的球體的片段數(shù)量是堆疊數(shù)量的2倍,就是
iStacks = 2 * iSlices - 繪制球體都是圍繞Z軸,這樣
+z就是球體的頂點(diǎn),-z就是球體的底部
gltMakeSphere(sphereBatch, 3.0, 10, 20);
d、渲染場(chǎng)景
用當(dāng)前清除顏色清除窗口背景
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
模型視圖矩陣棧堆,壓棧?;蛘邔?duì)objectFrame進(jìn)行壓棧,刪掉3.和4. 直接進(jìn)入switch(nStep)的判斷步驟
modelViewMatrix.PushMatrix();
modelViewMatrix.PushMatrix(objectFrame);
獲取攝像頭矩陣,從camereaFrame中獲取矩陣到mCamera
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
模型視圖堆棧的矩陣與mCamera矩陣相乘之后,存儲(chǔ)到modelViewMatrix矩陣堆棧中
modelViewMatrix.MultMatrix(mCamera);
創(chuàng)建矩陣mObjectFrame,從ObjectFrame獲取矩陣到mOjectFrame中
M3DMatrix44f mObjectFrame;
objectFrame.GetMatrix(mObjectFrame);
將modelViewMatrix的堆棧中的矩陣與mOjbectFrame矩陣相乘,存儲(chǔ)到modelViewMatrix矩陣堆棧中
modelViewMatrix.MultMatrix(mObjectFrame);
判斷目前是繪制第幾個(gè)圖形
switch(nStep)
{
case 0:
DrawWireFramedBatch(&sphereBatch);
break;
case 1:
DrawWireFramedBatch(&torusBatch);
break;
case 2:
DrawWireFramedBatch(&cylinderBatch);
break;
case 3:
DrawWireFramedBatch(&coneBatch);
break;
case 4:
DrawWireFramedBatch(&diskBatch);
break;
}
出棧
modelViewMatrix.PopMatrix();
交換緩存
glutSwapBuffers();
e、繪制圖形和邊框
? 繪制圖形
平面著色器,繪制三角形
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
傳過(guò)來(lái)的參數(shù)對(duì)應(yīng)不同的圖形Batch
pBatch->Draw();
? 開(kāi)啟多邊形偏移
glEnable(GL_POLYGON_OFFSET_LINE);
將多邊形背面設(shè)為線(xiàn)框模式
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
開(kāi)啟多邊形偏移(設(shè)置偏移數(shù)量)
glPolygonOffset(-1.0f, -1.0f);
線(xiàn)條寬度
glLineWidth(2.5f);
? 開(kāi)啟混合功能(顏色混合&抗鋸齒功能)
glEnable(GL_BLEND);
開(kāi)啟處理線(xiàn)段抗鋸齒功能使線(xiàn)條更加柔和
glEnable(GL_LINE_SMOOTH);
設(shè)置顏色混合因子
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
? 平面著色器繪制線(xiàn)條
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
pBatch->Draw();
? 恢復(fù)多邊形模式和深度測(cè)試
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glLineWidth(1.0f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
2、繪制其他圖形
環(huán)面
- torusBatch:三角形批次類(lèi)對(duì)象
- majorRadius:甜甜圈中心到外邊緣的半徑
- minorRadius:甜甜圈中心到內(nèi)邊緣的半徑
- numMajor:沿著主半徑的三角形數(shù)量
- numMinor:沿著內(nèi)部較小半徑的三角形數(shù)量
gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);

圓柱
- cylinderBatch:三角形批次類(lèi)對(duì)象
- baseRadius:底部半徑
- topRadius:頭部半徑
- fLength:圓形長(zhǎng)度
- numSlices:圍繞Z軸的三角形對(duì)的數(shù)量
- numStacks:圓柱底部堆疊到頂部圓環(huán)的三角形數(shù)量
gltMakeCylinder(cylinderBatch, 2.0f, 2.0f, 3.0f, 15, 2);

圓錐體
- cylinderBatch:三角形批次類(lèi)對(duì)象
- baseRadius:底部半徑
- topRadius:頭部半徑
- fLength:圓形長(zhǎng)度
- numSlices:圍繞Z軸的三角形對(duì)的數(shù)量
- numStacks:圓柱底部堆疊到頂部圓環(huán)的三角形數(shù)量
- 圓柱體,從0開(kāi)始向Z軸正方向延伸。圓錐體,是一端的半徑為0,另一端半徑可指定
gltMakeCylinder(coneBatch, 2.0f, 0.0f, 3.0f, 13, 2);

磁盤(pán)
- diskBatch:三角形批次類(lèi)對(duì)象
- innerRadius:內(nèi)圓半徑
- outerRadius:外圓半徑
- nSlices:圓盤(pán)圍繞Z軸的三角形對(duì)的數(shù)量
- nStacks:圓盤(pán)外網(wǎng)到內(nèi)圍的三角形數(shù)量
gltMakeDisk(diskBatch, 1.5f, 3.0f, 13, 3);

3、繪制自動(dòng)旋轉(zhuǎn)的球體

void RenderScene(void)
{
}
? 建立基于時(shí)間變化的動(dòng)畫(huà)
static CStopWatch rotTimer;
當(dāng)前時(shí)間 * 60s
float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
? 矩陣變量
- mTranslate:平移
- mRotate:旋轉(zhuǎn)
- mModelview:模型視圖
- mModelViewProjection:模型視圖投影MVP
M3DMatrix44f mTranslate, mRotate, mModelview, mModelViewProjection;
? 仿射變換
創(chuàng)建一個(gè)4*4矩陣變量,將球體沿著Z軸負(fù)方向移動(dòng)2.5個(gè)單位長(zhǎng)度
m3dTranslationMatrix44(mTranslate, 0.0f, 0.0f, -2.5f);
創(chuàng)建一個(gè)4*4矩陣變量,將球體在Y軸上旋轉(zhuǎn)yRot度,yRot根據(jù)經(jīng)過(guò)時(shí)間設(shè)置動(dòng)畫(huà)幀率
m3dRotationMatrix44(mRotate, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);
mModerView通過(guò)矩陣旋轉(zhuǎn)矩陣、移動(dòng)矩陣相乘,將結(jié)果添加到mModerView上
m3dMatrixMultiply44(mModelview, mTranslate, mRotate);
將投影矩陣乘以模型視圖矩陣,將變化結(jié)果通過(guò)矩陣乘法應(yīng)用到mModelViewProjection矩陣上
m3dMatrixMultiply44(mModelViewProjection, viewFrustum.GetProjectionMatrix(),mModelview);
? 著色器繪圖
繪圖顏色
GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
通過(guò)平面著色器提交矩陣和顏色
shaderManager.UseStockShader(GLT_SHADER_FLAT, mModelViewProjection, vBlack);
開(kāi)始繪圖
torusBatch.Draw();
交換緩沖區(qū),并立即刷新
glutSwapBuffers();
glutPostRedisplay();
4、繪制圍繞太陽(yáng)旋轉(zhuǎn)的地球

a、使用到的屬性
GLShaderManager shaderManager; // 著色器管理器
GLMatrixStack modelViewMatrix; // 模型視圖矩陣
GLMatrixStack projectionMatrix; // 投影矩陣
GLFrustum viewFrustum; // 視景體
GLGeometryTransform transformPipeline; // 幾何圖形變換管道
GLTriangleBatch torusBatch; // 大球
GLTriangleBatch sphereBatch; // 小球(隨機(jī)球,包括靜止和自轉(zhuǎn)兩種類(lèi)型)
GLBatch floorBatch; // 地板
// 角色幀 照相機(jī)角色幀
GLFrame cameraFrame;
// 添加附加隨機(jī)球
#define NUM_SPHERES 50
GLFrame spheres[NUM_SPHERES];
b、添加數(shù)據(jù)源
void SetupRC()
{
}
清空顏色緩沖區(qū)中的殘留顏色值,再進(jìn)行初始化
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
shaderManager.InitializeStockShaders();
開(kāi)啟深度測(cè)試
glEnable(GL_DEPTH_TEST);
設(shè)置地板頂點(diǎn)數(shù)據(jù)
floorBatch.Begin(GL_LINES, 324);// 共324個(gè)
for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5)
{
// 地板是平面,只會(huì)在X、Y上發(fā)生變化
floorBatch.Vertex3f(x, -0.55f, 20.0f);
floorBatch.Vertex3f(x, -0.55f, -20.0f);
floorBatch.Vertex3f(20.0f, -0.55f, x);
floorBatch.Vertex3f(-20.0f, -0.55f, x);
}
floorBatch.End();
設(shè)置大球模型
gltMakeSphere(torusBatch, 0.4f, 40, 80);
設(shè)置小球球模型
gltMakeSphere(sphereBatch, 0.1f, 26, 13);
隨機(jī)位置放置小球
for (int i = 0; i < NUM_SPHERES; I++)
{
// 小球在同一個(gè)平面,說(shuō)明Y軸不變,X,Z使用隨機(jī)值
GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
// 在y軸方向,將球體設(shè)置為0.0的位置,這使得它們看起來(lái)是飄浮在眼睛的高度
// 對(duì)spheres數(shù)組中的每一個(gè)頂點(diǎn),設(shè)置頂點(diǎn)數(shù)據(jù)
spheres[i].SetOrigin(x, 0.0f, z);
}
c、渲染場(chǎng)景
void RenderScene(void)
{
}
顏色值(地板、大球、小球顏色)
static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f};
static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
static GLfloat vSphereColor[] = { 0.0f, 0.0f, 1.0f, 1.0f};
清除顏色緩存區(qū)和深度緩沖區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
時(shí)間動(dòng)畫(huà)
static CStopWatch rotTimer;
float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
為了讓藍(lán)色的小球的公轉(zhuǎn)在任何角度都能看到需要加入觀察者。觀察者放在地板之前,讓地板也支持?jǐn)z影機(jī)的移動(dòng)
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.PushMatrix(mCamera);
使用平面著色器繪制地板
shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);
floorBatch.Draw();
獲取光源位置(固定管線(xiàn)里面都是4維矩陣的計(jì)算)
M3DVector4f vLightPos = {0.0f,10.0f,5.0f,1.0f};
畫(huà)中央的紅色大球
- 移動(dòng)觀察者
camera進(jìn)行平移 - 使用
objectFrame移動(dòng)物體自身,最終還是調(diào)用了modelViewMatrix - 使用
modelViewMatrix移動(dòng)物體自身
// 使得大球位置平移(3.0)向屏幕里面
modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
// 壓棧(復(fù)制棧頂),只有當(dāng)圖形發(fā)生了仿射變換的時(shí)候才需要使用到堆棧
modelViewMatrix.PushMatrix();
// 大球自轉(zhuǎn)(圍繞Y軸旋轉(zhuǎn))
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
// 指定合適的著色器(點(diǎn)光源著色器)
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(), vLightPos, vTorusColor);
torusBatch.Draw();
// 繪制完畢則Pop
modelViewMatrix.PopMatrix();
畫(huà)靜態(tài)的小球
for (int i = 0; i < NUM_SPHERES; I++)
{
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(spheres[I]);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(), vLightPos, vSphereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
讓一個(gè)小籃球圍繞大球公眾自轉(zhuǎn)
// 圍繞Y軸繞負(fù)方向2倍速度旋轉(zhuǎn)
modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
// 因?yàn)榛@球和紅球位置都在中央,為區(qū)分,將籃球沿著X軸正方向移動(dòng)0.8
modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vSphereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
執(zhí)行緩存區(qū)交換
glutSwapBuffers();
為了讓球旋轉(zhuǎn)起來(lái),需要進(jìn)行不斷渲染
glutPostRedisplay();
d、屏幕更改大小或已初始化
void ChangeSize(int nWidth, int nHeight)
{
}
設(shè)置視口
glViewport(0, 0, nWidth, nHeight);
創(chuàng)建投影矩陣
viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
獲取viewFrustum投影矩陣,并將其加載到投影矩陣堆棧上
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
設(shè)置變換管道以使用兩個(gè)矩陣堆棧(變換矩陣modelViewMatrix ,投影矩陣projectionMatrix)。
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
e、鍵盤(pán)操作上下平移和左右旋轉(zhuǎn)
void SpeacialKeys(int key,int x,int y)
{
// 移動(dòng)步長(zhǎng)
float linear = 0.1f;
// 旋轉(zhuǎn)度數(shù)
float angular = float(m3dDegToRad(5.0f));
......
}
上下平移
if (key == GLUT_KEY_UP)
{
cameraFrame.MoveForward(linear);
}
if (key == GLUT_KEY_DOWN)
{
cameraFrame.MoveForward(-linear);
}
左右旋轉(zhuǎn)
if (key == GLUT_KEY_LEFT)
{
cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
}
if (key == GLUT_KEY_RIGHT)
{
cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
}
三、OpenGL紋理
1、繪制金字塔


// 紋理變量,一般使用無(wú)符號(hào)整型
GLuint textureID;
a、添加數(shù)據(jù)源
void SetupRC()
{
glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
shaderManager.InitializeStockShaders();
glEnable(GL_DEPTH_TEST);
.....
}
分配紋理對(duì)象
- 參數(shù)1:紋理對(duì)象個(gè)數(shù)
- 參數(shù)2:紋理對(duì)象指針
glGenTextures(1, &textureID);
綁定紋理狀態(tài)
- 參數(shù)1:紋理狀態(tài)2D
- 參數(shù)2:紋理對(duì)象
glBindTexture(GL_TEXTURE_2D, textureID);
將TGA文件加載為2D紋理
- 參數(shù)1:紋理文件名稱(chēng)
- 參數(shù)2&參數(shù)3:需要縮小&放大的過(guò)濾器
- 參數(shù)4:紋理坐標(biāo)環(huán)繞模式
LoadTGATexture("stone.tga", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, GL_CLAMP_TO_EDGE);
創(chuàng)造金字塔pyramidBatch
設(shè)置金字塔頂點(diǎn)坐標(biāo)數(shù)據(jù)/紋理坐標(biāo)數(shù)據(jù)
MakePyramid(pyramidBatch);
修改觀察者,將相機(jī)平移
cameraFrame.MoveForward(-10);
b、將TGA文件加載為2D紋理
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
// 指向圖像數(shù)據(jù)的指針
GLbyte *pBits;
// 圖片的寬、高、顏色
int nWidth, nHeight, nComponents;
// 顏色存儲(chǔ)方式
GLenum eFormat;
.....
}
讀取紋理位置,讀取像素
- 參數(shù)1:紋理文件名稱(chēng)
- 參數(shù)2:文件寬度地址
- 參數(shù)3:文件高度地址
- 參數(shù)4:文件組件地址
- 參數(shù)5:文件格式地址
- 返回值:指向圖像數(shù)據(jù)的指針
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
if(pBits == NULL) return false;// 未能成功讀取到數(shù)據(jù)
設(shè)置紋理參數(shù)
- 參數(shù)1:紋理維度
- 參數(shù)2:為S/T坐標(biāo)設(shè)置模式(線(xiàn)性過(guò)濾)
- 參數(shù)3:環(huán)繞模式(過(guò)濾方式)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
載入紋理
- 參數(shù)1:紋理維度
- 參數(shù)2:貼圖層次
- 參數(shù)3:紋理單元存儲(chǔ)的顏色成分(從讀取像素圖是獲得)
- 參數(shù)4:加載紋理寬
- 參數(shù)5:加載紋理高
- 參數(shù)6:加載紋理的深度
-
參數(shù)7:像素?cái)?shù)據(jù)的數(shù)據(jù)類(lèi)型(
GL_UNSIGNED_BYTE,每個(gè)顏色分量都是一個(gè)8位無(wú)符號(hào)整數(shù)) - 參數(shù)8:指向紋理圖像數(shù)據(jù)的指針
glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);
// 使用完畢釋放pBits
free(pBits);
紋理生成所有的Mip層
glGenerateMipmap(GL_TEXTURE_2D);
c、繪制金字塔
void MakePyramid(GLBatch& pyramidBatch)
{
}
? 通過(guò)pyramidBatch組建三角形批次
- 參數(shù)1:圖元枚舉值
- 參數(shù)2:頂點(diǎn)數(shù)
- 參數(shù)3:這個(gè)批次中將會(huì)應(yīng)用1個(gè)紋理,如果不寫(xiě)這個(gè)參數(shù),默認(rèn)為0
pyramidBatch.Begin(GL_TRIANGLES, 18, 1);
? 創(chuàng)建頂點(diǎn)數(shù)據(jù)
M3DVector3f vApex = { 0.0f, 1.0f, 0.0f };// 塔頂
M3DVector3f vFrontLeft = { -1.0f, -1.0f, 1.0f };// 前左
M3DVector3f vFrontRight = { 1.0f, -1.0f, 1.0f };// 前右
M3DVector3f vBackLeft = { -1.0f, -1.0f, -1.0f };// 后左
M3DVector3f vBackRight = { 1.0f, -1.0f, -1.0f };// 后右
M3DVector3f n;// 法線(xiàn)變量
? 繪制金字塔底部四邊形中的三角形X(vBackLeft,vBackRight,vFrontRight)
- 找到三角形X的法線(xiàn)
// 參數(shù)1:結(jié)果
// 參數(shù)2-4:3個(gè)頂點(diǎn)數(shù)據(jù)
m3dFindNormal(n, vBackLeft, vBackRight, vFrontRight);
- vBackLeft
// 添加一個(gè)表面法線(xiàn)。表面法線(xiàn)是有方向的向量,法線(xiàn)坐標(biāo)與Vertex頂點(diǎn)坐標(biāo)中的Y軸一致。
pyramidBatch.Normal3fv(n);// 設(shè)置法線(xiàn)
// texture:紋理層次,使用存儲(chǔ)著色器來(lái)進(jìn)行渲染,設(shè)置為0
// s:對(duì)應(yīng)頂點(diǎn)坐標(biāo)中的x坐標(biāo)
// t:對(duì)應(yīng)頂點(diǎn)坐標(biāo)中的y
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);// 設(shè)置紋理坐標(biāo)
pyramidBatch.Vertex3fv(vBackLeft);// 向三角形批次類(lèi)添加頂點(diǎn)數(shù)據(jù)
- vBackRight
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackRight);
- vFrontRight
pyramidBatch.Normal3fv(n);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
pyramidBatch.Vertex3fv(vFrontRight);
? 按照繪制三角形X的步驟繪制金字塔各面的三角形
? 結(jié)束批次設(shè)置
pyramidBatch.End();
d、繪制場(chǎng)景
顏色值&光源位置
static GLfloat vLightPos [] = { 1.0f, 1.0f, 0.0f };
static GLfloat vWhite [] = { 1.0f, 1.0f, 1.0f, 1.0f };
清理緩存區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
當(dāng)前模型視頻壓棧
modelViewMatrix.PushMatrix();
// 添加照相機(jī)矩陣
M3DMatrix44f mCamera;
// 從camraFrame中獲取一個(gè)4*4的矩陣
cameraFrame.GetCameraMatrix(mCamera);
// 矩陣乘以矩陣堆棧頂部矩陣,相乘結(jié)果存儲(chǔ)到堆棧的頂部將照相機(jī)矩陣與當(dāng)前模型矩陣相乘壓入棧頂
modelViewMatrix.MultMatrix(mCamera);
// 創(chuàng)建mObjectFrame矩陣
M3DMatrix44f mObjectFrame;
// 從objectFrame中獲取矩陣,objectFrame保存的是特殊鍵位的變換矩陣
objectFrame.GetMatrix(mObjectFrame);
// 矩陣乘以矩陣堆棧頂部矩陣,相乘結(jié)果存儲(chǔ)到堆棧的頂部將照相機(jī)矩陣與當(dāng)前模型矩陣相乘壓入棧頂
modelViewMatrix.MultMatrix(mObjectFrame);
綁定紋理。因?yàn)槲覀兊捻?xiàng)目中只有一個(gè)紋理,可以省略這步,但如果有多個(gè)紋理,綁定紋理很重要
glBindTexture(GL_TEXTURE_2D, textureID);
點(diǎn)光源著色器
- 參數(shù)1:GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF(著色器標(biāo)簽)
- 參數(shù)2:模型視圖矩陣
- 參數(shù)3:投影矩陣
- 參數(shù)4:視點(diǎn)坐標(biāo)系中的光源位置
- 參數(shù)5:基本漫反射顏色
- 參數(shù)6:圖形顏色(用紋理就不需要設(shè)置顏色,設(shè)置為0)
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos, vWhite, 0);
繪制金字塔
pyramidBatch.Draw();
模型視圖出棧,恢復(fù)矩陣(push一次就要pop一次)
modelViewMatrix.PopMatrix();
交換緩存區(qū)
glutSwapBuffers();
e、進(jìn)行清理,例如刪除紋理對(duì)象
void ShutdownRC(void)
{
glDeleteTextures(1, &textureID);
}
2、繪制隧道


a、使用到的屬性
4個(gè)批次容器類(lèi)
GLBatch floorBatch;//地面
GLBatch ceilingBatch;//天花板
GLBatch leftWallBatch;//左墻面
GLBatch rightWallBatch;//右墻面
深度初始值為-65
GLfloat viewZ = -65.0f;
紋理標(biāo)識(shí)符號(hào)
#define TEXTURE_BRICK 0 //墻面
#define TEXTURE_FLOOR 1 //地板
#define TEXTURE_CEILING 2 //紋理天花板
#define TEXTURE_COUNT 3 //紋理個(gè)數(shù)
紋理標(biāo)記數(shù)組
GLuint textures[TEXTURE_COUNT];
文件tag名字?jǐn)?shù)組
const char *szTextureFiles[TEXTURE_COUNT] = { "brick.tga", "floor.tga", "ceiling.tga" };
b、輔助函數(shù)中的修改
在main函數(shù)中添加菜單入口,改變過(guò)濾器
glutCreateMenu(ProcessMenu);
glutAddMenuEntry("GL_NEAREST",0);
glutAddMenuEntry("GL_LINEAR",1);
glutAddMenuEntry("GL_NEAREST_MIPMAP_NEAREST",2);
glutAddMenuEntry("GL_NEAREST_MIPMAP_LINEAR", 3);
glutAddMenuEntry("GL_LINEAR_MIPMAP_NEAREST", 4);
glutAddMenuEntry("GL_LINEAR_MIPMAP_LINEAR", 5);
glutAddMenuEntry("Anisotropic Filter", 6);
glutAddMenuEntry("Anisotropic Off", 7);
glutAttachMenu(GLUT_RIGHT_BUTTON);
在ChangeSize函數(shù)中生成透視投影
GLfloat fAspect = (GLfloat)w/(GLfloat)h;
viewFrustum.SetPerspective(80.0f,fAspect,1.0,120.0);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
前后移動(dòng)視口來(lái)對(duì)方向鍵作出響應(yīng)的函數(shù)中改變的是深度值Z
if(key == GLUT_KEY_UP) viewZ += 0.5f;
if(key == GLUT_KEY_DOWN) viewZ -= 0.5f;
關(guān)閉渲染環(huán)境函數(shù)中刪除紋理
glDeleteTextures(TEXTURE_COUNT, textures);
c、菜單欄選擇
綁定紋理
void ProcessMenu(int value)
{
GLint iLoop;
for(iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
{
// 綁定紋理
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
.......
}
}
// 觸發(fā)重畫(huà)
glutPostRedisplay();
}
配置紋理參數(shù)
// 0-縮小過(guò)濾器、最鄰近過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// 1-縮小過(guò)濾器、線(xiàn)性過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// 2-縮小過(guò)濾器、選擇最鄰近的Mip層,并執(zhí)行最鄰近過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
// 3-縮小過(guò)濾器、在Mip層之間執(zhí)行線(xiàn)性插補(bǔ),并執(zhí)行最鄰近過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
// 4-縮小過(guò)濾器、選擇最鄰近Mip層,并執(zhí)行線(xiàn)性過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
// 5-縮小過(guò)濾器、在Mip層之間執(zhí)行線(xiàn)性插補(bǔ),并執(zhí)行線(xiàn)性過(guò)濾,又稱(chēng)為三線(xiàn)性過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// 6
// 設(shè)置各向異性過(guò)濾
GLfloat fLargest;
// 獲取各向異性過(guò)濾的最大數(shù)量
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
// 設(shè)置紋理參數(shù)(各向異性采樣)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
// 7-設(shè)置各向同性過(guò)濾,數(shù)量為1.0表示(各向同性采樣)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
d、設(shè)置數(shù)據(jù)源
void SetupRC()
{
glClearColor(0.0f, 0.0f, 0.0f,1.0f);// 黑色的背景
shaderManager.InitializeStockShaders();
GLbyte *pBytes;
GLint iWidth, iHeight, iComponents;
GLenum eFormat;
GLint iLoop;
// 分配紋理對(duì)象
glGenTextures(TEXTURE_COUNT, textures);
// 循環(huán)設(shè)置紋理數(shù)組的紋理參數(shù)
for(iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
{
......
}
}
綁定紋理對(duì)象
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
加載tga文件
pBytes = gltReadTGABits(szTextureFiles[iLoop],&iWidth, &iHeight, &iComponents, &eFormat);
加載紋理、設(shè)置過(guò)濾器和包裝模式
// 放大過(guò)濾器、最鄰近過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// 縮小過(guò)濾器、最鄰近過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// s軸環(huán)繞、環(huán)繞模式強(qiáng)制對(duì)范圍之外的紋理坐標(biāo)沿著合法的紋理單元的最后一行或一列進(jìn)行采樣
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
// t軸環(huán)繞、環(huán)繞模式強(qiáng)制對(duì)范圍之外的紋理坐標(biāo)沿著合法的紋理單元的最后一行或一列進(jìn)行采樣
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
載入紋理 glTexImage2D
glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
為紋理對(duì)象生成一組完整的mipmap
glGenerateMipmap(GL_TEXTURE_2D);
釋放原始紋理數(shù)據(jù),不在需要紋理原始數(shù)據(jù)了
free(pBytes);
設(shè)置圖形上下左右各面的頂點(diǎn)/紋理坐標(biāo)
GLfloat z;// 隧道的深度
floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
// 地板墻面
for(z = 60.0f; z >= 0.0f; z -=10.0f)
{
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Vertex3f(-10.0f, -10.0f, z);
floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
floorBatch.Vertex3f(10.0f, -10.0f, z);
floorBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
floorBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);
floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
floorBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);
}
floorBatch.End();
// 天花板墻面
......
// 左面墻面
.....
// 右面墻面
.....
e、渲染場(chǎng)景
void RenderScene(void)
{
// 用當(dāng)前清除色,清除窗口
glClear(GL_COLOR_BUFFER_BIT);
// 模型視圖壓棧
modelViewMatrix.PushMatrix();
......
// 模型視圖出棧
modelViewMatrix.PopMatrix();
// 緩存區(qū)交換
glutSwapBuffers();
}
在Z軸上平移viewZ距離
modelViewMatrix.Translate(0.0f, 0.0f, viewZ);
紋理替換矩陣著色器
- 參數(shù)1:GLT_SHADER_TEXTURE_REPLACE(著色器標(biāo)簽)
- 參數(shù)2:模型視圖投影矩陣
- 參數(shù)3:紋理層
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE, transformPipeline.GetModelViewProjectionMatrix(), 0);
綁定紋理
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
floorBatch.Draw();
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
ceilingBatch.Draw();
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
leftWallBatch.Draw();
rightWallBatch.Draw();
3、繪制自動(dòng)旋轉(zhuǎn)的球體世界



a、使用到的屬性
添加附加隨機(jī)球
#define NUM_SPHERES 50
GLFrame spheres[NUM_SPHERES];
批處理容器
GLTriangleBatch torusBatch; // 花托批處理
GLBatch floorBatch; // 地板批處理
GLTriangleBatch sphereBatch; //公轉(zhuǎn)球的批處理
照相機(jī)角色幀
GLFrame cameraFrame;
紋理標(biāo)記數(shù)組
GLuint uiTextures[3];
b、設(shè)置數(shù)據(jù)源
void SetupRC()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
shaderManager.InitializeStockShaders();
.....
}
開(kāi)啟深度測(cè)試/背面剔除
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
設(shè)置大球、小球(公轉(zhuǎn)自轉(zhuǎn))
gltMakeSphere(torusBatch, 0.4f, 40, 80);
gltMakeSphere(sphereBatch, 0.1f, 26, 13);
設(shè)置地板頂點(diǎn)數(shù)據(jù)&地板紋理
GLfloat texSize = 10.0f;
floorBatch.Begin(GL_TRIANGLE_FAN, 4,1);
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Vertex3f(-20.f, -0.41f, 20.0f);
floorBatch.MultiTexCoord2f(0, texSize, 0.0f);
floorBatch.Vertex3f(20.0f, -0.41f, 20.f);
floorBatch.MultiTexCoord2f(0, texSize, texSize);
floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
floorBatch.MultiTexCoord2f(0, 0.0f, texSize);
floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
floorBatch.End();
隨機(jī)小球頂點(diǎn)坐標(biāo)數(shù)據(jù)
for (int i = 0; i < NUM_SPHERES; I++)
{
GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
spheres[i].SetOrigin(x, 0.0f, z);
}
命名紋理對(duì)象
glGenTextures(3, uiTextures);
將TGA文件加載為2D紋理
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
LoadTGATexture("marslike.tga", GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
LoadTGATexture("moonlike.tga", GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, GL_CLAMP_TO_EDGE);
c、繪制地板和球
void drawSomething(GLfloat yRot)
{
}
定義光源位置&漫反射顏色
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
繪制懸浮小球
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
for(int i = 0; i < NUM_SPHERES; I++)
{
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(spheres[I]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos,
vWhite,
0);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
// 繪制大球
........
// 繪制公轉(zhuǎn)自轉(zhuǎn)小球
.......
d、渲染場(chǎng)景
void RenderScene(void)
{
......
}
添加反光效果
// 壓棧(鏡面)
modelViewMatrix.PushMatrix();
// 翻轉(zhuǎn)Y軸
modelViewMatrix.Scale(1.0f, -1.0f, 1.0f);
// 鏡面世界圍繞Y軸平移一定間距
modelViewMatrix.Translate(0.0f, 0.8f, 0.0f);
// 指定順時(shí)針為正面
glFrontFace(GL_CW);
// 繪制地面以外其他部分(鏡面)
drawSomething(yRot);
// 恢復(fù)為逆時(shí)針為正面
glFrontFace(GL_CCW);
// 繪制鏡面,恢復(fù)矩陣
modelViewMatrix.PopMatrix();
開(kāi)啟混合功能(繪制地板)
glEnable(GL_BLEND);
// 指定glBlendFunc 顏色混合方程式
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// 綁定地面紋理
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
// 紋理調(diào)整著色器(將一個(gè)基本色乘以一個(gè)取自紋理的單元nTextureUnit的紋理)
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor,
0);
// 開(kāi)始繪制
floorBatch.Draw();
// 取消混合
glDisable(GL_BLEND);
Demo
Demo在我的Github上,歡迎下載。
Multi-MediaDemo