1. 程式人生 > >opengl超級寶典(第五版)閱讀筆記 3 基本圖元的使用

opengl超級寶典(第五版)閱讀筆記 3 基本圖元的使用

基本圖元有 GL_POINTS GL_LINES GL_LINE_STRIP GL_LINE_LOOP GL_TRIANGLES GL_TRIANGLE_LOOP GL_TRIANGLE_FAN.
後面將一 一對其進行簡單的介紹
1.GL_POINTS
I. 建立點集

GLfloat vCoast[24][3] = { { 2.80, 1.20, 0.0 },{ 2.0, 1.20, 0.0 },
{ 2.0, 1.08, 0.0 },{ 2.0, 1.08, 0.0 },
{ 0.0, 0.80, 0.0 },{ -.32, 0.40, 0.0 },
{ -.48, 0.2, 0.0 },{ -.40, 0.0, 0.0 },
{ -.60, -
.40, 0.0 },{ -.80, -.80, 0.0 }, { -.80, -1.4, 0.0 },{ -.40, -1.60, 0.0 }, { 0.0, -1.20, 0.0 },{ .2, -.80, 0.0 }, { .48, -.40, 0.0 },{ .52, -.20, 0.0 }, { .48, .20, 0.0 },{ .80, .40, 0.0 }, { 1.20, .80, 0.0 },{ 1.60, .60, 0.0 }, { 2.0, .60, 0.0 },{ 2.2, .80, 0.0 }, { 2.40, 1.0, 0.0 },{ 2.80, 1.0, 0.0 } };

II. 載入點圖

GLBatch pointBatch;
pointBatch.Begin(GL_POINTS,
24); pointBatch.CopyVertexData3f(vCoast); pointBatch.End(); III. 改變點的大小 glPointSize(4.0f);

IV. 繪製

pointBatch.Draw();

V效果圖
在這裡插入圖片描述
2.GL_LINES
這是線段,把數組裡面的0-1相連 2-3相連 ,以此類推。
絕大部分操作都和上面一樣的,只需替換GL_POINTS成GL_LINES即可,
效果圖如下:
在這裡插入圖片描述
3.GL_LINE_STRIP GL_LINE_LOOP
GL_LINE_STRIP是把陣列中的端點依次連線起來,但是首尾不相連,而GL_LINE_LOOP首尾相連。
效果圖分別如下:
在這裡插入圖片描述


在這裡插入圖片描述
4.GL_TRIANGLES
繪製立體圖形的時候如果邊緣部分不能顯示出來會很沒有立體感,如下圖所示
在這裡插入圖片描述
因此,需要繪製出來邊緣部分,其主要程式碼如下:
//通過偏移值繪製邊緣部分

    void DrawWireFramedBatch(GLBatch* pBatch)
    {
           // Draw the batch solid green  
           shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
           pBatch->Draw();
           // Draw black outline  
           glPolygonOffset(-1.0f, -1.0f);      // 設定偏移值
           glEnable(GL_POLYGON_OFFSET_LINE);//開啟偏移
           // Draw lines antialiased  
           glEnable(GL_LINE_SMOOTH);//對直線進行抗鋸齒處理
           glEnable(GL_BLEND);//開啟混合
           glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//設定混合引數
           // Draw black wireframe version of geometry  
           glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//用線來繪製多邊形
           glLineWidth(2.5f);//線寬
           shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);//選擇著色器
           pBatch->Draw();//開始繪製
           // Put everything back the way we found it  
           glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//還原填充模式
           glDisable(GL_POLYGON_OFFSET_LINE);//關閉線性偏移
           glLineWidth(1.0f);//還原線寬
           glDisable(GL_BLEND);//關閉混合
           glDisable(GL_LINE_SMOOTH);//關閉直線的抗鋸齒處理
    }

然後我們建立好三角形座標

   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 };
   //載入好三角形
   triangleBatch.Begin(GL_TRIANGLES, 12);
   triangleBatch.CopyVertexData3f(vPyramid);
   triangleBatch.End();

通過DrawWireFramedBatch(&triangleBatch);繪製出來圖形,效果如下:
在這裡插入圖片描述

5.GL_TRIANGLE_LOOP
上面繪製多個三角形的時候,每個三角形都使用了三個頂點,而實際上,相鄰的三角形之間還存在著重複邊,而GL_TRIANGLE_LOOP會繪製陣列中連續的三個點作為三角形 0,1,2 1,2,3 2,3,4…
我們建立好三角形的座標

   int iCounter = 0;
   GLfloat radius = 3.0f;
   for (GLfloat angle = 0.0f; angle <= (2.0f*M3D_PI); angle += 0.3f)
   {
          GLfloat x = radius * sin(angle);
          GLfloat y = radius * cos(angle);
          // Specify the point and move the Z value up a little     
          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++;
   }
   // Close up the loop  
   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++;
   //載入扇形帶的圖元
   triangleStripBatch.Begin(GL_TRIANGLE_STRIP, iCounter);
   triangleStripBatch.CopyVertexData3f(vPoints);
   triangleStripBatch.End();

繪製三角形帶 DrawWireFramedBatch(&triangleStripBatch);
效果圖如下:
在這裡插入圖片描述

6.GL_TRIANGLE_FAN
原理和上面一樣,但是三角形的應對規則變了,變為 0,1,2 0,2,3 0,3,4 0,4,5… 看起來就是以第一個點為中心的扇形環
建立三角形扇的座標

       GLfloat vPoints[100][3];    // Scratch array, more than we need  
       int nVerts = 0;
       GLfloat r = 3.0f;
       vPoints[nVerts][0] = 0.0f;
       vPoints[nVerts][1] = 0.0f;
       vPoints[nVerts][2] = 0.0f;
       for (GLfloat angle = 0; angle < M3D_2PI; angle += M3D_2PI / 6.0f) {
              nVerts++;
              vPoints[nVerts][0] = float(cos(angle)) * r;//每個點的座標就是cosr和sinr
              vPoints[nVerts][1] = float(sin(angle)) * r;
              vPoints[nVerts][2] = -0.5f;
       }
       // 保證閉合
       nVerts++;
       vPoints[nVerts][0] = r;
       vPoints[nVerts][1] = 0;
       vPoints[nVerts][2] = 0.0f;
       // 載入三角形扇,頂點+6個端點+最後一個保證閉合的初始點=8個點
       triangleFanBatch.Begin(GL_TRIANGLE_FAN, 8);
       triangleFanBatch.CopyVertexData3f(vPoints);
       triangleFanBatch.End();

繪製三角形扇
DrawWireFramedBatch(&triangleFanBatch);
效果圖如下:
在這裡插入圖片描述

完整程式碼還加入了按鍵控制旋轉,以及空格切換圖形,具體程式碼和註釋如下:

#include <GLTools.h>  // OpenGL toolkit  
#include <GLMatrixStack.h>  
#include <GLFrame.h>  
#include <GLFrustum.h>  
#include <GLBatch.h>  
#include <GLGeometryTransform.h>
#define FREEGLUT_STATIC  //在windows和linux上,使用freeglut靜態版本,需要新增這一行,否則會出現錯誤
#include <glut.h>
#pragma comment(lib,"gltools.lib")//要加上這一行連結一下gltools庫
GLShaderManager     shaderManager;
GLMatrixStack       modelViewMatrix;
GLMatrixStack       projectionMatrix;
GLFrame             cameraFrame;//儲存了位置和兩個方向向量
GLFrame             objectFrame;
GLFrustum           viewFrustum;
GLBatch             pointBatch;
GLBatch             lineBatch;
GLBatch             lineStripBatch;
GLBatch             lineLoopBatch;
GLBatch             triangleBatch;
GLBatch             triangleStripBatch;
GLBatch             triangleFanBatch;
GLGeometryTransform transformPipeline;
M3DMatrix44f        shadowMatrix;
GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// Keep track of effects step  
int nStep = 0;
///////////////////////////////////////////////////////////////////////////////  
// This function does any needed initialization on the rendering context.   
// This is the first opportunity to do any OpenGL related tasks.  
void SetupRC()
{
       glClearColor(0.7f, 0.7f, 0.7f, 1.0f);//設定背景顏色為灰色
       shaderManager.InitializeStockShaders();//初始化著色器管理器
       glEnable(GL_DEPTH_TEST);//開啟深度測試
       transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);//設定變換管線以使用兩個矩陣的堆疊
       cameraFrame.MoveForward(-15.0f);//把攝像機往後挪一挪,否則看不到影象
       //////////////////////////////////////////////////////////////////////  
       // 一系列點的座標
       GLfloat vCoast[24][3] = { { 2.80, 1.20, 0.0 },{ 2.0,  1.20, 0.0 },
       { 2.0,  1.08, 0.0 },{ 2.0,  1.08, 0.0 },
       { 0.0,  0.80, 0.0 },{ -.32, 0.40, 0.0 },
       { -.48, 0.2, 0.0 },{ -.40, 0.0, 0.0 },
       { -.60, -.40, 0.0 },{ -.80, -.80, 0.0 },
       { -.80, -1.4, 0.0 },{ -.40, -1.60, 0.0 },
       { 0.0, -1.20, 0.0 },{ .2, -.80, 0.0 },
       { .48, -.40, 0.0 },{ .52, -.20, 0.0 },
       { .48,  .20, 0.0 },{ .80,  .40, 0.0 },
       { 1.20, .80, 0.0 },{ 1.60, .60, 0.0 },
       { 2.0, .60, 0.0 },{ 2.2, .80, 0.0 },
       { 2.40, 1.0, 0.0 },{ 2.80, 1.0, 0.0 } };
       // 載入好點圖 
       pointBatch.Begin(GL_POINTS, 24);
       pointBatch.CopyVertexData3f(vCoast);
       pointBatch.End();
       // 載入好線段圖
       lineBatch.Begin(GL_LINES, 24);
       lineBatch.CopyVertexData3f(vCoast);
       lineBatch.End();
       // 載入好連續的線的圖
       lineStripBatch.Begin(GL_LINE_STRIP, 24);
       lineStripBatch.CopyVertexData3f(vCoast);
       lineStripBatch.End();
       // 載入好首尾相連的連續的線的圖
       lineLoopBatch.Begin(GL_LINE_LOOP, 24);
       lineLoopBatch.CopyVertexData3f(vCoast);
       lineLoopBatch.End();
       // 金字塔的點的座標 ,四個面
       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 };
       //載入好三角形
       triangleBatch.Begin(GL_TRIANGLES, 12);
       triangleBatch.CopyVertexData3f(vPyramid);
       triangleBatch.End();
       //初始化三角形扇的座標
       GLfloat vPoints[100][3];    // Scratch array, more than we need  
       int nVerts = 0;
       GLfloat r = 3.0f;
       vPoints[nVerts][0] = 0.0f;
       vPoints[nVerts][1] = 0.0f;
       vPoints[nVerts][2] = 0.0f;
       for (GLfloat angle = 0; angle < M3D_2PI; angle += M3D_2PI / 6.0f) {
              nVerts++;
              vPoints[nVerts][0] = float(cos(angle)) * r;//每個點的座標就是cosr和sinr
              vPoints[nVerts][1] = float(sin(angle)) * r;
              vPoints[nVerts][2] = -0.5f;
       }
       // 保證閉合
       nVerts++;
       vPoints