6转晰、OpenGL初探之OpenGL渲染基礎(chǔ)綜合實戰(zhàn)

OpenGL初識之OpenGL渲染基礎(chǔ)概念傳送門http://www.reibang.com/p/d26879a736af

接著上一節(jié)我們學(xué)習(xí)了OpenGL渲染基礎(chǔ)许饿,現(xiàn)在我們來綜合使用一下,練習(xí)一下繪制OpenGL圖元并組合圖元:

一眼姐、繪制圖元點
二者蠕、繪制圖元線段/連續(xù)線段/線環(huán)
三窃祝、繪制金字塔
四、圖元渲染三角形帶/三角形扇

一踱侣、繪制圖元點


先上繪制的總結(jié)思路圖


OpenGL渲染業(yè)務(wù)介紹.png

開始準(zhǔn)備環(huán)境和對應(yīng)的函數(shù)(詳細介紹請移步我之前的文章,傳送門:基本函數(shù)解釋http://www.reibang.com/p/b98be0925051)
這里主要說明有區(qū)別的地方

1粪小、設(shè)置全局變量

GLShaderManager shaderManager;//著色器管理
GLMatrixStack modelViewMatrix;//模型視圖矩陣堆棧
GLMatrixStack projectViewMatrix;//投影矩陣堆棧
GLFrame cameraFrame;//觀察者
GLFrame objectFrame;

GLFrustum viewFrustum;//投影矩陣

//批次類(7種不同的圖元,對應(yīng)7種容器對象)
GLBatch pointBatch;//點
GLBatch lineBatch;//線
GLBatch lineStripBatch;//連線
GLBatch lineLoopBatch;//線環(huán)
GLBatch triangleBatch;//三級形
GLBatch triangleStripBatch;//三角形帶
GLBatch triangleFanBatch;//三角形扇

//幾何變換管道
GLGeometryTransform transformPipeline;
//顏色RGBA
GLfloat vGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
GLfloat vYellow[] = {1.0f,1.0f, 0.0f, 1.0f};
//設(shè)置按空格鍵來切換不同圖元展示
//記錄按了幾次空格
int nStep = 0;

2泻仙、設(shè)置main函數(shù)

int main(int argc,char* argv[]){
    
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
    glutInitWindowSize(800,600);
    glutCreateWindow("Triangle");
    
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    glutSpecialFunc(SpecialKeys);
    
    //注冊點擊空格會調(diào)用的函數(shù)
    glutKeyboardFunc(KeyPressFunc);
    
    GLenum err = glewInit();
    if(GLEW_OK != err) {
        fprintf(stderr,"glew error:%s\n",glewGetErrorString(err));
        return 1;
    }
    
    SetupRC();
    glutMainLoop();
    return 0;
}

3糕再、設(shè)置SetupRC函數(shù),注釋我都寫在里面了

    //1、設(shè)置背景顏色
    glClearColor(0.7f, 0.7f, 0.7f,1.0);
    //2玉转、初始化著色器管理器
    shaderManager.InitializeStockShaders();
    //3突想、開啟深度測試
    glEnable(GL_DEPTH_TEST);
    //4、設(shè)置變換管道
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectViewMatrix);
    //5究抓、設(shè)置觀察者位置猾担,便于觀察效果
    cameraFrame.MoveForward(-15);
    
    //6、設(shè)置一些點
    //創(chuàng)建一維的六個點的數(shù)組
    GLfloat vCoast[18] = {
        3,3,0,
        -3,3,0,
        3,0,0,
        -3,0,0,
        3,-3,0,
        -3,-3,0
    };

    //設(shè)置圖元渲染方式刺下,點
    pointBatch.Begin(GL_POINTS, 6);
    pointBatch.CopyVertexData3f(vCoast);
    pointBatch.End();

4绑嘹、設(shè)置ChangeSize函數(shù),需要注意的是,這個函數(shù)的調(diào)用時機橘茉,就是窗口已更改大小工腋,或剛剛創(chuàng)建,無論是那種情況畅卓,我們都需要使用窗口維度設(shè)置視口和設(shè)置投影矩陣

    //1擅腰、設(shè)置視口
    glViewport(0, 0, w, h);
    //2、投影矩陣: 需要設(shè)置縱橫比
    viewFrustum.SetPerspective(35, floorf(w) / floorf(h), 1.0, 500);
    //3翁潘、設(shè)置投影矩陣,加載投影矩陣
projectViewMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    //4趁冈、模型視圖視圖矩陣堆棧,加載單元矩陣
    modelViewMatrix.LoadIdentity();

5、設(shè)置渲染RenderScence函數(shù)

    //1渗勘、清除緩沖區(qū)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //2沐绒、模型視圖矩陣---壓棧
    modelViewMatrix.PushMatrix();
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.MultMatrix(mCamera);//矩陣相乘,得到變換后的新矩陣
    
    M3DMatrix44f mObjectFrame;
    objectFrame.GetMatrix(mObjectFrame);    
    modelViewMatrix.MultMatrix(mObjectFrame);//矩陣相乘旺坠,得到變換后的新矩陣

    //3乔遮、挑選平面著色器渲染
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
    
    
    //4、容器類提交繪制
    switch (nStep) {
        case 0:
            //設(shè)置點的大小
            glPointSize(20.0f);
            pointBatch.Draw();
            glPointSize(1.0f);
            break;
            
                default:
            break;
    }
    
    //5价淌、模型視圖矩陣---出棧申眼,還原到以前的模型視圖矩陣
    modelViewMatrix.PopMatrix();
    //6、交換緩沖區(qū)
    glutSwapBuffers();

6蝉衣、設(shè)置特殊鍵位函數(shù)

void SpecialKeys (int key , int x, int y){
    //點擊鍵盤上的上下左右鍵
    if (key == GLUT_KEY_UP) {
        //往上移動,圍繞X軸巷蚪,是順時針方向病毡,由于逆時針為正,所以是-5.0
        //m3dDegToRad() 角度轉(zhuǎn)弧度函數(shù)
        objectFrame.RotateWorld(m3dDegToRad(-5.0), 1.0, 0, 0);//其中的1.0表示YES屁柏,0.0表示NO
    }else if (key == GLUT_KEY_DOWN) {
        //往下移動啦膜,圍繞X軸,是逆時針方向淌喻,由于逆時針為正僧家,所以是5.0
        objectFrame.RotateWorld(m3dDegToRad(5.0), 1.0, 0, 0);
    }else if (key == GLUT_KEY_LEFT) {
        //往左移動,圍繞Y軸裸删,是順時針方向八拱,由于逆時針為正,所以是-5.0
        objectFrame.RotateWorld(m3dDegToRad(-5.0), 0.0, 1.0, 0);
    }else if (key == GLUT_KEY_RIGHT) {
        //往右移動涯塔,圍繞Y軸肌稻,是逆時針方向,由于逆時針為正匕荸,所以是5.0
        objectFrame.RotateWorld(m3dDegToRad(5.0), 0.0, 1.0, 0);
    }
   
    //發(fā)生變化需要重新渲染
    glutPostRedisplay();
}

7爹谭、設(shè)置空格切換函數(shù)KeyPressFunc(這個主要是用來切換不同圖元)

void KeyPressFunc(unsigned char key, int x, int y){
    //不斷點擊空格修改nStep記錄步數(shù)
    if(key == 32){
        nStep++;
        
        if(nStep > 6){
            nStep = 0;
        }
    }
    //修改窗口名稱
    switch(nStep)
    {
        case 0:
            glutSetWindowTitle("GL_POINTS");
            break;
        case 1:
            glutSetWindowTitle("GL_LINES");
            break;
        case 2:
            glutSetWindowTitle("GL_LINE_STRIP");
            break;
        case 3:
            glutSetWindowTitle("GL_LINE_LOOP");
            break;
        case 4:
            glutSetWindowTitle("GL_TRIANGLES");
            break;
        case 5:
            glutSetWindowTitle("GL_TRIANGLE_STRIP");
            break;
        case 6:
            glutSetWindowTitle("GL_TRIANGLE_FAN");
            break;
    }
    
    glutPostRedisplay();
}


二、繪制圖元線段/連續(xù)線段/線環(huán)


繪制圖元點的寫完后榛搔,設(shè)置繪制圖元線段/連續(xù)線段/線環(huán) 诺凡,只需要配置SetupRC里面設(shè)置對應(yīng)圖元,然后再RenderScence修改圖元繪制就行了践惑,對應(yīng)修改的位置如下

1腹泌、修改SetupRC部分代碼

    //1/設(shè)置圖元渲染方式,點
    pointBatch.Begin(GL_POINTS, 6);
    pointBatch.CopyVertexData3f(vCoast);
    pointBatch.End();
    
    //2/設(shè)置圖元渲染方式,線段
    lineBatch.Begin(GL_LINES, 6);
    lineBatch.CopyVertexData3f(vCoast);
    lineBatch.End();
    
    //3/設(shè)置圖元渲染方式童本,連續(xù)線段
    lineStripBatch.Begin(GL_LINE_STRIP, 6);
    lineStripBatch.CopyVertexData3f(vCoast);
    lineStripBatch.End();
    
    //4/設(shè)置圖元渲染方式,線環(huán)
    lineLoopBatch.Begin(GL_LINE_LOOP, 6);
    lineLoopBatch.CopyVertexData3f(vCoast);
    lineLoopBatch.End();

2真屯、修改RenderScence對應(yīng)部分代碼

switch (nStep) {
        case 0:
            //設(shè)置點的大小
            glPointSize(20.0f);
            pointBatch.Draw();
            glPointSize(1.0f);
            break;
            
        case 1:
            //設(shè)置線段寬度
            glLineWidth(5.0f);
            lineBatch.Draw();
            glLineWidth(1.0f);
            break;
            
        case 2:
            //
            glLineWidth(5.0f);
            lineStripBatch.Draw();
            glLineWidth(1.0f);
            break;
        case 3:
            glLineWidth(5.0f);
            lineLoopBatch.Draw();
            glLineWidth(1.0f);
            
            break;
            
        default:
            break;
    }


三、渲染圖元金字塔


接下來我們繪制金字塔穷娱,金字塔是由一個底面和四個側(cè)面組成绑蔫,金字塔沒有底面的話运沦,其實側(cè)面是由4個三角形組成的,如果有底面的話配深,底面是兩個三角形組成的携添,和上面不同圖元繪制的方式類似,只需要修改SetupRC和RenderScene對應(yīng)的代碼就行了

1篓叶、SetupRC函數(shù)中設(shè)置金字塔四個頂點坐標(biāo)數(shù)據(jù)和圖元裝配方式

    //設(shè)置金字塔的頂點數(shù)據(jù)
    //通過三角形創(chuàng)建金字塔
    GLfloat vPyramid[12][3] = {
        -2.0f, 0.0f, -2.0f,
        2.0f, 0.0f, -2.0f,
        0.0f, 4.0f, 0.0f,
        
        2.0f, 0.0f, -2.0f,
        2.0f, 0.0f, 2.0f,
        0.0f, 4.0f, 0.0f,
        
        2.0f, 0.0f, 2.0f,
        -2.0f, 0.0f, 2.0f,
        0.0f, 4.0f, 0.0f,
        
        -2.0f, 0.0f, 2.0f,
        -2.0f, 0.0f, -2.0f,
        0.0f, 4.0f, 0.0f};

    //GL_TRIANGLES 每3個頂點定義一個新的三角形
    triangleBatch.Begin(GL_TRIANGLES, 12);
    triangleBatch.CopyVertexData3f(vPyramid);
    triangleBatch.End();


2烈掠、RenderScence繪制金字塔

    case 4:
        triangleBatch.Draw();
        break;

四、圖元渲染三角形扇/圖元渲染三角形帶


1缸托、繪制六邊形三角形扇
修改SetupRC左敌,設(shè)置頂點數(shù)據(jù),該頂點的坐標(biāo)數(shù)據(jù)是通過半徑和角度求來的俐镐,下面這段代碼的循環(huán)矫限,就是為了求六邊形七個頂點的位置坐標(biāo),六個頂點和一個中心點

// 三角形扇形--六邊形
    GLfloat vPoints[100][3];
    int nVerts = 0;
    //半徑
    GLfloat r = 3.0f;
    //原點(x,y,z) = (0,0,0);
    vPoints[nVerts][0] = 0.0f;
    vPoints[nVerts][1] = 0.0f;
    vPoints[nVerts][2] = 0.0f;
    
    //M3D_2PI 就是2Pi 的意思佩抹,就一個圓的意思叼风。 繪制圓形
    for(GLfloat angle = 0; angle < M3D_2PI; angle += M3D_2PI / 6.0f) {
        
        //數(shù)組下標(biāo)自增(每自增1次就表示一個頂點)
        nVerts++;
        /*
         弧長=半徑*角度,這里的角度是弧度制,不是平時的角度制
         既然知道了cos值,那么角度=arccos,求一個反三角函數(shù)就行了
         */
        //x點坐標(biāo) cos(angle) * 半徑
        vPoints[nVerts][0] = float(cos(angle)) * r;
        //y點坐標(biāo) sin(angle) * 半徑
        vPoints[nVerts][1] = float(sin(angle)) * r;
        //z點的坐標(biāo)
        vPoints[nVerts][2] = -0.5f;
    }
    
    // 結(jié)束扇形 前面一共繪制7個頂點(包括圓心)
    //添加閉合的終點
    //如果屏蔽173-177行代碼,并把繪制節(jié)點改為7.則三角形扇形是無法閉合的棍苹。
    nVerts++;
    vPoints[nVerts][0] = r;
    vPoints[nVerts][1] = 0;
    vPoints[nVerts][2] = 0.0f;
    
    // 加載无宿!
    //GL_TRIANGLE_FAN 以一個圓心為中心呈扇形排列,共用相鄰頂點的一組三角形
    triangleFanBatch.Begin(GL_TRIANGLE_FAN, 8);
    triangleFanBatch.CopyVertexData3f(vPoints);
    triangleFanBatch.End();

2枢里、繪制六邊形三角形扇,修改RenderScence

    case 6:   
        triangleFanBatch.Draw();
        break;

3孽鸡、繪制三角形帶,配置頂點坐標(biāo)以及圖元裝配方式

//三角形條帶坡垫,一個小環(huán)或圓柱段
    //頂點下標(biāo)
    int iCounter = 0;
    //半徑
    GLfloat radius = 3.0f;
    //從0度~360度梭灿,以0.3弧度為步長
    for(GLfloat angle = 0.0f; angle <= (2.0f*M3D_PI); angle += 0.3f)
    {
        //或許圓形的頂點的X,Y
        GLfloat x = radius * sin(angle);
        GLfloat y = radius * cos(angle);
        
        //繪制2個三角形(他們的x,y頂點一樣,只是z點不一樣)
        vPoints[iCounter][0] = x;
        vPoints[iCounter][1] = y;
        vPoints[iCounter][2] = -0.5;
        iCounter++;
        
        vPoints[iCounter][0] = x;
        vPoints[iCounter][1] = y;
        vPoints[iCounter][2] = 0.5;
        iCounter++;
    }
    
    // 關(guān)閉循環(huán)
    //結(jié)束循環(huán)冰悠,在循環(huán)位置生成2個三角形
    vPoints[iCounter][0] = vPoints[0][0];
    vPoints[iCounter][1] = vPoints[0][1];
    vPoints[iCounter][2] = -0.5;
    iCounter++;
    
    vPoints[iCounter][0] = vPoints[1][0];
    vPoints[iCounter][1] = vPoints[1][1];
    vPoints[iCounter][2] = 0.5;
    iCounter++;
    
    // GL_TRIANGLE_STRIP 共用一個條帶(strip)上的頂點的一組三角形
    triangleStripBatch.Begin(GL_TRIANGLE_STRIP, iCounter);
    triangleStripBatch.CopyVertexData3f(vPoints);
    triangleStripBatch.End();

4堡妒、繪制三角形帶,修改RenderScence

    case 5:
        triangleStripBatch.Draw();
        break;

運行得到所有的樣式,如下圖:


圖元繪制實戰(zhàn).png

溪浣雙鯉的技術(shù)摸爬滾打之路

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末溉卓,一起剝皮案震驚了整個濱河市皮迟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌桑寨,老刑警劉巖伏尼,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尉尾,居然都是意外死亡爆阶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辨图,“玉大人班套,你說我怎么就攤上這事」屎樱” “怎么了吱韭?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鱼的。 經(jīng)常有香客問我理盆,道長,這世上最難降的妖魔是什么凑阶? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任猿规,我火速辦了婚禮,結(jié)果婚禮上晌砾,老公的妹妹穿的比我還像新娘坎拐。我一直安慰自己,他們只是感情好养匈,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著都伪,像睡著了一般呕乎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陨晶,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天猬仁,我揣著相機與錄音,去河邊找鬼先誉。 笑死湿刽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的褐耳。 我是一名探鬼主播诈闺,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼铃芦!你這毒婦竟也來了雅镊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤刃滓,失蹤者是張志新(化名)和其女友劉穎仁烹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咧虎,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡卓缰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片征唬。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡捌显,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鳍鸵,到底是詐尸還是另有隱情苇瓣,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布偿乖,位于F島的核電站击罪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贪薪。R本人自食惡果不足惜媳禁,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望画切。 院中可真熱鬧竣稽,春花似錦、人聲如沸霍弹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽典格。三九已至岛宦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耍缴,已是汗流浹背砾肺。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留防嗡,地道東北人变汪。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像蚁趁,于是被迫代替她去往敵國和親裙盾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容