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