復(fù)習(xí)下基本流程
初始化glut模塊
加載配置模塊
設(shè)置窗口大小
給窗口取個(gè)名字
注冊一個(gè)方法監(jiān)測窗口改變
注冊一個(gè)方法監(jiān)測鍵盤輸入
注冊一個(gè)方法監(jiān)測屏幕刷新
初始化glew模塊并檢測是否初始化成功
設(shè)置默認(rèn)值(環(huán)境)
加載并啟動(dòng)MainLoop
實(shí)際上并不需要完全按照上面的步驟來做尉桩,像注冊監(jiān)測的那三個(gè)方法可以自由變換順序妄呕。
具體代碼:
//著色器管理類
GLShaderManager shaderManager;
//甜甜圈容器
GLTriangleBatch donutBatch;
//窗口改變
void ChangeSize(int w, int h) { }
//監(jiān)測鍵盤輸入信號
void SpecialKeys(int key, int x, int y) { }
//屏幕刷新
void RenderScene() { }
//初始化相關(guān)工作
void SetupRC() { }
int main( int argc, char *argv[]) {
gltSetWorkingDirectory(argv[0]);
//初始化glut模塊
glutInit(&argc, argv);
//加載配置模塊
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
//設(shè)置窗口大小
glutInitWindowSize(400, 400);
//給窗口取個(gè)名字
glutCreateWindow("There is a donut here");
//注冊一個(gè)方法監(jiān)測窗口改變
glutReshapeFunc(ChangeSize);
//注冊一個(gè)方法監(jiān)測鍵盤輸入
glutSpecialFunc(SpecialKeys);
注冊一個(gè)方法監(jiān)測屏幕刷新
glutDisplayFunc(RenderScene);
//初始化glew模塊并檢測是否初始化成功
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
//設(shè)置默認(rèn)值(環(huán)境)
SetupRC();
//加載并啟動(dòng)MainLoop
glutMainLoop();
return 0;
}
繪制甜甜圈的準(zhǔn)備工作
1.因?yàn)檫@次是要畫一個(gè)可以展覽的甜甜圈(不然就沒有靈魂了),所以我們需要有一個(gè)觀察者吝沫,也就是攝影師(觀察者坐標(biāo)系)
,且觀察者自身也有一個(gè)屬性(物體坐標(biāo)系)
GLMatrixStack cameraMatix;
GLFrame cameraFrame;
2.而甜甜圈自身也是有大小的阳仔,所以我們需要描繪甜甜圈的屬性(物體坐標(biāo)系)
GLMatrixStack donutMatrix;
3.在將甜甜圈轉(zhuǎn)化為世界坐標(biāo)系的時(shí)候掸冤,需要設(shè)置甜甜圈的投影規(guī)則(稱之為管線
)
GLGeometryTransform donutTransform;
4.這次需要繪制的是立體的甜甜圈,所以為了有立體感食呻,需要設(shè)置投影方式為透視投影
流炕,為此,我們需要設(shè)置一個(gè)全局變量用于記錄當(dāng)前透視狀態(tài)
GLFrustum viewFrustum;
初始化工作
在SetupRC
中需要設(shè)置背景顏色仅胞,初始化全局變量
glClearColor(240/255.0, 248/255.0, 255/255.0, 1.0f);
shaderManager.InitializeStockShaders();
//將相機(jī)向后移動(dòng)7個(gè)單元:肉眼到物體之間的距離
cameraFrame.MoveForward(7.0);
//創(chuàng)建一個(gè)甜甜圈
//void gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
//參數(shù)1:GLTriangleBatch 容器幫助類
//參數(shù)2:外邊緣半徑
//參數(shù)3:內(nèi)邊緣半徑
//參數(shù)4浪感、5:主半徑和從半徑的細(xì)分單元數(shù)量
gltMakeTorus(donutBatch, 1.0f, 0.3f, 52, 26);
窗口改變時(shí)
//1.防止h變?yōu)?
if(h == 0)
h = 1;
//2.設(shè)置視口窗口尺寸
glViewport(0, 0, w, h);
//3.setPerspective函數(shù)的參數(shù)是一個(gè)從頂點(diǎn)方向看去的視場角度(用角度值表示)
// 設(shè)置透視模式,初始化其透視矩陣
viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);
//4.把透視矩陣加載到透視矩陣對陣中
donutMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//5.初始化渲染管線
donutTransform.SetMatrixStacks(cameraMatix, donutMatrix);
屏幕刷新時(shí)
//1.清除窗口和深度緩沖區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//2.把攝像機(jī)矩陣壓入模型矩陣中
cameraMatix.PushMatrix(cameraFrame);
//3.設(shè)置繪圖顏色
GLfloat colorDonut[] = { 255/255.0, 215/255.0, 0/255.0, 1.0f };
//4.
//使用平面著色器
//參數(shù)1:平面著色器
//參數(shù)2:模型視圖投影矩陣
//參數(shù)3:顏色
// shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vRed);
//使用默認(rèn)光源著色器
//通過光源饼问、陰影效果跟提現(xiàn)立體效果
//參數(shù)1:GLT_SHADER_DEFAULT_LIGHT 默認(rèn)光源著色器
//參數(shù)2:模型視圖矩陣
//參數(shù)3:投影矩陣
//參數(shù)4:基本顏色值
shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, donutTransform.GetModelViewMatrix(), donutTransform.GetProjectionMatrix(), colorDonut);
//5.繪制
donutBatch.Draw();
//6.出棧 繪制完成恢復(fù)
cameraMatix.PopMatrix();
//7.交換緩存區(qū)
glutSwapBuffers();
Run一下影兽,發(fā)現(xiàn)甜甜圈出現(xiàn)了,開心~
但是莱革,這是一個(gè)不會(huì)動(dòng)的甜甜圈>摺6锟!
為了讓他動(dòng)起來捐名,我們必須進(jìn)行操作
在SpecialKey
中
//監(jiān)測鍵盤輸入信號
void SpecialKeys(int key, int x, int y) {
//w 設(shè)置為后空翻吧旦万,就是圍繞x軸向后旋轉(zhuǎn)
if(key == 119)
cameraFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);
//s 設(shè)置為前空翻吧,就是圍繞x軸向前旋轉(zhuǎn)
if(key == 115)
cameraFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);
//a 設(shè)置為直立順時(shí)針轉(zhuǎn)圈镶蹋,就是圍繞y軸順時(shí)針旋轉(zhuǎn)
if(key == 97)
cameraFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);
//d 設(shè)置為直立順時(shí)針轉(zhuǎn)圈成艘,就是圍繞y軸逆時(shí)針旋轉(zhuǎn)
if(key == 100)
cameraFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);
//q 設(shè)置為正向中心順時(shí)針轉(zhuǎn)圈,就是圍繞z軸逆時(shí)針旋轉(zhuǎn)
if(key == 113)
cameraFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 0.0f, 1.0f);
//e 設(shè)置為正向中心逆時(shí)針轉(zhuǎn)圈贺归,就是圍繞z軸逆時(shí)針旋轉(zhuǎn)
if(key == 101)
cameraFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 0.0f, 1.0f);
//3.重新刷新
glutPostRedisplay();
}
再Run一下淆两,棒~想要的效果出來了!??????????
又又又又又但是拂酣!在旋轉(zhuǎn)的時(shí)候秋冰,出現(xiàn)了很多黑色的東西,色香味色先掛了婶熬,哪里還有食欲剑勾?想要解決它,首先得了解它是什么赵颅。
在現(xiàn)實(shí)世界中虽另,一個(gè)甜甜圈還沒開始吃的時(shí)候,應(yīng)該只能看到它脆脆的皮饺谬,而不可能看到它松松的肉洲赵,但是在我們繪制的甜甜圈中,我們看到了它松松的肉商蕴,這是不正常的。
在OpenGL的世界中芝发,所描繪的每一個(gè)物體都是有它的正面和背面的绪商,正面不會(huì)被遮擋,而背面會(huì)被遮擋住辅鲸,用這樣的方式來模擬現(xiàn)實(shí)世界中不透明的物體的成像格郁。
因此現(xiàn)在的這種情況,我們只需要打開OpenGL自身的
背面剔除
功能就好了独悴,所以在RenderScene
繪制的時(shí)候我們需要設(shè)置背面剔除
.
glEnable(GL_CULL_FACE);
再run一次例书,發(fā)現(xiàn)不再出現(xiàn)黑色了,??????????
但是又來了刻炒,這次决采,黑色沒有了,可旋轉(zhuǎn)到某一個(gè)方向的時(shí)候坟奥,出現(xiàn)了透視的現(xiàn)象树瞭,這是為什么呢拇厢?
在這次的甜甜圈的世界里,因?yàn)椴捎玫氖怯彤嫷漠嫹ㄉ古纾聪犬嫷紫峦繉拥男①耍佼嬌厦嫱繉樱虼肆骨茫瑘D形的正面與背面是已經(jīng)設(shè)定好了的衣盾,所以在旋轉(zhuǎn)的時(shí)候,由于正面位于背面的涂層下面爷抓,但是正面是不會(huì)被背面所遮擋的势决,所以便出現(xiàn)了透視的效果
該怎么做呢?先看一下下一篇OpenGL的深度測試把废赞,深度測試可以幫我們定位很多問題徽龟!