OpenGL綜合案例

OpenGL已經(jīng)學(xué)習(xí)了一段時間遇绞,現(xiàn)在進行一下綜合整理工作键袱。

繪制地板

以下是詳細代碼及注釋,這里不再做一一解釋,這里只摘錄了changeSize摹闽、SetupRC蹄咖、RenderScene這幾個方法中的代碼,其他代碼及他們的執(zhí)行流程付鹿,可以參照之前文章:

GLShaderManager shaderManager; // 著色器管理器

GLMatrixStack? ? ? ? modelViewMatrix;? ? ? ? // 模型視圖矩陣

GLMatrixStack? ? ? ? projectionMatrix;? ? ? ? // 投影矩陣

GLFrustum? ? ? ? ? ? viewFrustum;? ? ? ? ? ? // 視景體

GLGeometryTransform? ? transformPipeline;? ? ? ? // 幾何圖形變換管道

GLTriangleBatch? ? ? ? torusBatch;? ? ? ? ? ? //大球

GLTriangleBatch? ? sphereBatch;? ? ? ? ? ? //小球

GLBatch? ? ? ? ? ? ? ? floorBatch;? ? ? ? ? //地板

//角色幀 照相機角色幀

GLFrame? ? ? ? ? ? cameraFrame;

//**4澜汤、添加附加隨機球

#define NUM_SPHERES 50

GLFrame spheres[NUM_SPHERES];

//屏幕更改大小或已初始化

void changeSize(int w,int h)

{

? ? //設(shè)置視口大小

? ? glViewport(0, 0, w, h);

? ? //創(chuàng)建投影矩陣 并將它載入到投影矩陣堆棧中

? ? viewFrustum.SetPerspective(35.0f, (float)w/(float)h, 1.0f, 100.0f);

? ? //viewFrustum.GetProjectionMatrix()用來獲取投影矩陣

? ? projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());

? ? //3.設(shè)置變換管道以使用兩個矩陣堆棧(變換矩陣modelViewMatrix ,投影矩陣projectionMatrix)

? ? transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

}

//初始化操作

void setupRC()

{

? ? //進行初始化操作

? ? //1.清理顏色

? ? glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

? ? //初始化著色器

? ? shaderManager.InitializeStockShaders();

? ? //開啟深度測試

? ? glEnable(GL_DEPTH_TEST);

? ? //3. 使用批次類設(shè)置地板頂點數(shù)據(jù)

? ? floorBatch.Begin(GL_LINES, 324);

? ? for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5) {

? ? ? ? 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();

}

//進行調(diào)用以繪制場景

void RenderScene(void)

{

? ? //設(shè)置地板顏色值

? ? static GLfloat vFloorColor[] = {0.0f,1.0f,0.0f,1.0f};

? ? //2.清除顏色緩存區(qū)和深度緩沖區(qū)

? ? glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

? ? //3.繪制地面 GLT_SHADER_FLAT平面著色器

? ? shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);

? ? //進行繪制

? ? floorBatch.Draw();

? ? //交換緩沖區(qū)

? ? glutSwapBuffers();

}

執(zhí)行后結(jié)果:

繪制大球

代碼及注釋:

//以上面的代碼為基礎(chǔ)舵匾,changeSize中不需要更改俊抵,在setupRC設(shè)置大球模型

//設(shè)置大球模型? 因為OpenGL中自帶球類模型,不需要自己畫頂點坐梯,直接調(diào)用gltMakeSphere方法徽诲,使用批次類,傳對應(yīng)的參數(shù)及可吵血。

? ? gltMakeSphere(torusBatch, 0.4f, 40, 80);

//RenderScene中改動較大谎替,詳細代碼如下:

void RenderScene(void)

{

? ? //設(shè)置地板顏色值

? ? static GLfloat vFloorColor[] = {0.0f,1.0f,0.0f,1.0f};

? ? //設(shè)置大球顏色

? ? static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };


? ? //創(chuàng)建定時器,用于控制大球轉(zhuǎn)動

? ? static CStopWatch rotTimer;

? ? //得到大球每秒轉(zhuǎn)動的角度

? ? float yRot = rotTimer.GetElapsedSeconds() *60.0;


? ? //2.清除顏色緩存區(qū)和深度緩沖區(qū)

? ? glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


? ? //進行壓棧蹋辅,為了確保每次操作獨立钱贯,不影響其他操作? 每一次壓棧PushMatrix都要對應(yīng)一次出棧PopMatrix

? ? modelViewMatrix.PushMatrix();



? ? //3.繪制地面 GLT_SHADER_FLAT平面著色器

? ? shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);

? ? //進行繪制

? ? floorBatch.Draw();


? ? //用矩陣設(shè)置一處光源

? ? M3DVector4f vLightPos = {0.0f,10.0f,5.0f,1.0f};

? ? //為了獲得更好的觀察效果,讓大球想屏幕里移動3.0

? ? modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);

? ? //再次壓棧晕翠,為了下面的旋轉(zhuǎn)操作

? ? modelViewMatrix.PushMatrix();

? ? //大球繞y軸旋轉(zhuǎn)

? ? modelViewMatrix.Rotate(0.0f, 1.0f, 0.0f, 1.0f);

? ? //設(shè)置著色器(點光源著色器) 模型視圖變換矩陣? 投影矩陣 點光源位置 顏色值

? ? shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vTorusColor);

? ? //繪制

? ? torusBatch.Draw();

? ? //進行出棧 2次

? ? modelViewMatrix.PopMatrix();

? ? modelViewMatrix.PopMatrix();


? ? //交換緩沖區(qū)

? ? glutSwapBuffers();

? ? //重新提交渲染

? ? glutPostRedisplay();

}

執(zhí)行結(jié)果:


繪制多個小球

代碼如下:

//如添加大球時的操作喷舀,同樣SetupRC中添加小球模型,并隨機放置50個

//設(shè)置小球模型

? ? gltMakeSphere(sphereBatch, 0.2f, 13, 26);

? ? //隨機放置 NUM_SPHERES上面定義過的宏

? ? for (int i = 0; i < NUM_SPHERES; i++) {


? ? ? ? //y軸不變淋肾,X,Z產(chǎn)生隨機值 讓小球處于同一平面

? ? ? ? GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);

? ? ? ? GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);

? ? ? ? //在y方向硫麻,將球體設(shè)置為0.0的位置,這使得它們看起來是飄浮在眼睛的高度

? ? ? ? //對spheres數(shù)組中的每一個頂點樊卓,設(shè)置頂點數(shù)據(jù)

? ? ? ? spheres[i].SetOrigin(x, 0.0f, z);

? ? }

//同樣在RenderScene中去繪制這50個小球

//畫小球拿愧,for循環(huán)畫50個,單個小球畫法和大球差不多碌尔,不同的是通過壓棧來保持每一次小球的獨立

? ? 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();

? ? }

生成小球

小球圍繞大球轉(zhuǎn)動

代碼:

//在RenderScene方法中加入

//讓一個小籃球圍繞大球公眾自轉(zhuǎn)

? ? modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);

? ? modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);

? ? shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSphereColor);

? ? sphereBatch.Draw();



鍵位控制

代碼:

//mian函數(shù)中注冊鍵位控制函數(shù)

glutSpecialFunc(SpeacialKeys);

//通過相應(yīng)的操作控制移動旋轉(zhuǎn)

void SpeacialKeys(int key,int x,int y){

? ? //移動步長

? ? float linear = 0.1f;

? ? //旋轉(zhuǎn)度數(shù)

? ? float angular = float(m3dDegToRad(5.0f));

? ? //上

? ? if (key == GLUT_KEY_UP) {

? ? ? ? //MoveForward 平移

? ? ? ? cameraFrame.MoveForward(linear);

? ? }

? ? //下

? ? if (key == GLUT_KEY_DOWN) {

? ? ? ? cameraFrame.MoveForward(-linear);

? ? }

? ? //左

? ? if (key == GLUT_KEY_LEFT) {

? ? ? ? //RotateWorld 旋轉(zhuǎn)

? ? ? ? cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);

? ? }

? ? //右

? ? if (key == GLUT_KEY_RIGHT) {

? ? ? ? cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);

? ? }

}

//然后在RenderScene中加入一個觀察者 平移10步(地板,大球,小球,小小球)浇辜,通過移動觀察者來達到目的

? ? M3DMatrix44f mCamera;

? ? cameraFrame.GetCameraMatrix(mCamera);

? ? modelViewMatrix.PushMatrix(mCamera);


這里大球自轉(zhuǎn)券敌,小球圍繞大球公轉(zhuǎn)的案例就完成了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柳洋,一起剝皮案震驚了整個濱河市待诅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌熊镣,老刑警劉巖卑雁,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绪囱,居然都是意外死亡测蹲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門鬼吵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扣甲,“玉大人,你說我怎么就攤上這事齿椅×鹜冢” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵媒咳,是天一觀的道長粹排。 經(jīng)常有香客問我,道長涩澡,這世上最難降的妖魔是什么顽耳? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮妙同,結(jié)果婚禮上射富,老公的妹妹穿的比我還像新娘。我一直安慰自己粥帚,他們只是感情好胰耗,可當(dāng)我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芒涡,像睡著了一般柴灯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上费尽,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天赠群,我揣著相機與錄音,去河邊找鬼旱幼。 笑死查描,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冬三,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼匀油,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了勾笆?” 一聲冷哼從身側(cè)響起敌蚜,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匠襟,沒想到半個月后钝侠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡酸舍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了里初。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啃勉。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖双妨,靈堂內(nèi)的尸體忽然破棺而出淮阐,到底是詐尸還是另有隱情,我是刑警寧澤刁品,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布泣特,位于F島的核電站,受9級特大地震影響挑随,放射性物質(zhì)發(fā)生泄漏状您。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一兜挨、第九天 我趴在偏房一處隱蔽的房頂上張望膏孟。 院中可真熱鬧,春花似錦拌汇、人聲如沸柒桑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽魁淳。三九已至,卻和暖如春与倡,著一層夾襖步出監(jiān)牢的瞬間界逛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工蒸走, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仇奶,地道東北人。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像该溯,于是被迫代替她去往敵國和親岛抄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,922評論 2 361