原創(chuàng):知識(shí)探索型文章
創(chuàng)作不易,請(qǐng)珍惜日川,之后會(huì)持續(xù)更新淮阐,不斷完善
個(gè)人比較喜歡做筆記和寫總結(jié)叮阅,畢竟好記性不如爛筆頭哈哈,這些文章記錄了我的IOS成長(zhǎng)歷程泣特,希望能與大家一起進(jìn)步
溫馨提示:由于簡(jiǎn)書不支持目錄跳轉(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é)類型仇奶。雖然我們不必親自進(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ù)類型,能夠表示?個(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;
// 三角形批次類
GLTriangleBatch CC_Triangle;
// 球
GLTriangleBatch sphereBatch;
// 環(huán)
GLTriangleBatch torusBatch;
// 圓柱
GLTriangleBatch cylinderBatch;
// 錐
GLTriangleBatch coneBatch;
// 磁盤
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);
利用三角形批次類構(gòu)造圖形對(duì)象——球
- sphereBatch:三角形批次類對(duì)象
- fRadius:球體半徑
- iSlices:從球體底部堆疊到頂部的三角形帶的數(shù)量,其實(shí)球體是一圈一圈三角形帶組成
- iStacks:圍繞球體一圈排列的三角形對(duì)數(shù)
- 一個(gè)對(duì)稱性較好的球體的片段數(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è)為線框模式
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
開(kāi)啟多邊形偏移(設(shè)置偏移數(shù)量)
glPolygonOffset(-1.0f, -1.0f);
線條寬度
glLineWidth(2.5f);
? 開(kāi)啟混合功能(顏色混合&抗鋸齒功能)
glEnable(GL_BLEND);
開(kāi)啟處理線段抗鋸齒功能使線條更加柔和
glEnable(GL_LINE_SMOOTH);
設(shè)置顏色混合因子
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
? 平面著色器繪制線條
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:三角形批次類對(duì)象
- majorRadius:甜甜圈中心到外邊緣的半徑
- minorRadius:甜甜圈中心到內(nèi)邊緣的半徑
- numMajor:沿著主半徑的三角形數(shù)量
- numMinor:沿著內(nèi)部較小半徑的三角形數(shù)量
gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);
圓柱
- cylinderBatch:三角形批次類對(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:三角形批次類對(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);
磁盤
- diskBatch:三角形批次類對(duì)象
- innerRadius:內(nèi)圓半徑
- outerRadius:外圓半徑
- nSlices:圓盤圍繞Z軸的三角形對(duì)的數(shù)量
- nStacks:圓盤外網(wǎng)到內(nèi)圍的三角形數(shù)量
gltMakeDisk(diskBatch, 1.5f, 3.0f, 13, 3);
3、繪制自動(dòng)旋轉(zhuǎn)的球體
void RenderScene(void)
{
}
? 建立基于時(shí)間變化的動(dòng)畫
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)畫幀率
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)兩種類型)
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)畫
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();
獲取光源位置(固定管線里面都是4維矩陣的計(jì)算)
M3DVector4f vLightPos = {0.0f,10.0f,5.0f,1.0f};
畫中央的紅色大球
- 移動(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();
畫靜態(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蔫缸、鍵盤操作上下平移和左右旋轉(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:紋理文件名稱
- 參數(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:紋理文件名稱
- 參數(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è)置模式(線性過(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ù)類型(
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è)紋理,如果不寫這個(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;// 法線變量
? 繪制金字塔底部四邊形中的三角形X(vBackLeft,vBackRight,vFrontRight)
- 找到三角形X的法線
// 參數(shù)1:結(jié)果
// 參數(shù)2-4:3個(gè)頂點(diǎn)數(shù)據(jù)
m3dFindNormal(n, vBackLeft, vBackRight, vFrontRight);
- vBackLeft
// 添加一個(gè)表面法線炭玫。表面法線是有方向的向量,法線坐標(biāo)與Vertex頂點(diǎn)坐標(biāo)中的Y軸一致貌虾。
pyramidBatch.Normal3fv(n);// 設(shè)置法線
// 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);// 向三角形批次類添加頂點(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è)批次容器類
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ā)重畫
glutPostRedisplay();
}
配置紋理參數(shù)
// 0-縮小過(guò)濾器、最鄰近過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// 1-縮小過(guò)濾器耻姥、線性過(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í)行線性插補(bǔ)蒸健,并執(zhí)行最鄰近過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
// 4-縮小過(guò)濾器、選擇最鄰近Mip層婉商,并執(zhí)行線性過(guò)濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
// 5-縮小過(guò)濾器似忧、在Mip層之間執(zhí)行線性插補(bǔ),并執(zhí)行線性過(guò)濾据某,又稱為三線性過(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);
載入紋理 glTexImage
2D
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