[demo5].不畫甜甜圈的吃貨不是好的程序猿

跳去目錄


復(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();
不會(huì)動(dòng)的甜甜圈

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)象树瞭,這是為什么呢拇厢?

image.png

在這次的甜甜圈的世界里,因?yàn)椴捎玫氖怯彤嫷漠嫹ㄉ古纾聪犬嫷紫峦繉拥男①耍佼嬌厦嫱繉樱虼肆骨茫瑘D形的正面與背面是已經(jīng)設(shè)定好了的衣盾,所以在旋轉(zhuǎn)的時(shí)候,由于正面位于背面的涂層下面爷抓,但是正面是不會(huì)被背面所遮擋的势决,所以便出現(xiàn)了透視的效果
該怎么做呢?先看一下下一篇OpenGL的深度測試把废赞,深度測試可以幫我們定位很多問題徽龟!


跳去目錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市唉地,隨后出現(xiàn)的幾起案子据悔,更是在濱河造成了極大的恐慌,老刑警劉巖耘沼,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件极颓,死亡現(xiàn)場離奇詭異,居然都是意外死亡群嗤,警方通過查閱死者的電腦和手機(jī)菠隆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狂秘,“玉大人骇径,你說我怎么就攤上這事≌叽海” “怎么了破衔?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長钱烟。 經(jīng)常有香客問我晰筛,道長,這世上最難降的妖魔是什么拴袭? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任读第,我火速辦了婚禮,結(jié)果婚禮上拥刻,老公的妹妹穿的比我還像新娘怜瞒。我一直安慰自己,他們只是感情好般哼,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布盼砍。 她就那樣靜靜地躺著尘吗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浇坐。 梳的紋絲不亂的頭發(fā)上睬捶,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天,我揣著相機(jī)與錄音近刘,去河邊找鬼擒贸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛觉渴,可吹牛的內(nèi)容都是我干的介劫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼案淋,長吁一口氣:“原來是場噩夢啊……” “哼座韵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起踢京,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤誉碴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后瓣距,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體黔帕,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年蹈丸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了成黄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逻杖,死狀恐怖奋岁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荸百,我是刑警寧澤闻伶,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站管搪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏铡买。R本人自食惡果不足惜更鲁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奇钞。 院中可真熱鬧澡为,春花似錦、人聲如沸景埃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拒啰,卻和暖如春驯绎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谋旦。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工剩失, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人册着。 一個(gè)月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓拴孤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甲捏。 傳聞我的和親對象是個(gè)殘疾皇子演熟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348