OpenGL 基本图元绘制案例及解析

点、线、线路、闭合线路、金字塔、三角形带、三角形扇

案例结构

一、切换绘制场景

这些图形的绘制流程都是一样的:

初始化 -> 设置顶点坐标 -> 设置渲染参数 -> 渲染

为了方便学习,我们在同一个工程里面进行绘制。

设置一个参数 nStep, 点击空格的时候,修改其值,手动触发重新渲染。

在渲染参数设置方法里,设置 nStep 对应的图形渲染参数。

初始化 -> 设置顶点坐标(所有图形需要的顶点坐标) -> 设置渲染参数(根据 nStep 进行不同设置) -> 渲染

// 跟踪效果步骤

int nStep = 0;

// 空格键(32)切换绘制场景参数

voidKeyPressFunc(unsignedchar key, int x, int y){

if(key == 32) {

nStep++;

if(nStep > 6)

nStep = 0;

}

switch(nStep) {

case0:

glutSetWindowTitle("GL_POINTS");

break;

case1:

glutSetWindowTitle("GL_LINES");

break;

...

// 设置不同的窗口标题,篇幅原因 case 2~6 不写,可自行实现

}

// 图形类型切换,手动触发重新渲染

glutPostRedisplay();

}

// 注意,需要在 main 函数注册此方法

//点击空格时,调用的函数

glutKeyboardFunc(KeyPressFunc);

二、旋转物体

金字塔、三角形带、三角形扇都是立体图形,为了便于观察,我们还需要设置一个旋转操作,可以全方位查看绘制的图形。

// 物体坐标系

GLFrame objectFrame;

voidSpecialKeys(int key, int x, int y){

if(key == GLUT_KEY_UP)

//围绕一个指定的X,Y,Z轴旋转。

objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);

if(key == GLUT_KEY_DOWN)

objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);

if(key == GLUT_KEY_LEFT)

objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);

if(key == GLUT_KEY_RIGHT)

objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);

// 物体发生旋转,手动触发重新渲染

glutPostRedisplay();

}

// 注意,需要在 main 函数注册此方法

// 特殊键位函数(上下左右)

glutSpecialFunc(SpecialKeys);

三、设置窗口修改函数

GLMatrixStack		modelViewMatrix;

GLMatrixStack projectionMatrix;

// 投影矩阵,本案例需要绘制 3D 图形,因此使用透视投影效果更好

GLFrustum viewFrustum;

// 窗口已更改大小,或刚刚创建。无论哪种情况,我们都需要

// 使用窗口维度设置视口和投影矩阵.

voidChangeSize(int w, int h){

glViewport(0, 0, w, h);

// 创建视锥体

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

// 使用视锥体生成投影矩阵,并存储在 projectionMatrix 变量

projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());

// 初始化模型矩阵:载入一个单元矩阵

modelViewMatrix.LoadIdentity();

}

透视投影

透视投影 图片来源: LearnOpenGL-CN

  • 创建一个投影矩阵

// Calculates the corners of the Frustum and sets the projection matrix.

// Perspective Matrix Projection

voidSetPerspective(float fFov, float fAspect, float fNear, float fFar){...}

参数含义
fFov视锥体的角度,即视野
fAspect宽高比,由视口的宽除以高所得
fNear视点距离近平面的距离
fFar视点距离远平面的距离

近平面和远平面切割四棱锥,形成一个锥台,其间的物体会被观测到

当你把透视矩阵的 near 值设置太大时(如10.0f),OpenGL会将靠近摄像机的坐标(在0.0f和10.0f之间)都裁剪掉,这会导致一个你在游戏中很熟悉的视觉效果:在太过靠近一个物体的时候你的视线会直接穿过去。

现在我们的准备工作已经做好了,开始进行图形绘制流程。

四、设置顶点

在本次案例中,我们不需要修改顶点数据,只在初始化函数设置一次即可。

// 着色器管理类

GLShaderManager shaderManager;

// 几何变换的管道

GLGeometryTransform transformPipeline;

// 为点图形 创建批次类

GLBatch pointBatch;

// 此函数在呈现上下文中进行任何必要的初始化。.

// 这是第一次做任何与opengl相关的任务。

voidSetupRC(){

// 灰色的背景

glClearColor(0.7f, 0.7f, 0.7f, 1.0f );

shaderManager.InitializeStockShaders();

// 设置变换管道以使用两个矩阵堆栈

// ⚠️变换管线存储不是这两个变量的值,而是指针,当这两个矩阵重新赋值,变换管线读到的值也会变化

transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

// 设置视点,摄像机(视点)相对于物体,在z轴移动的距离。

// 在物体坐标系中,z轴正方向是向屏幕内的,所以设置为负值,值越小,距离物体越远,物体投影后,在整个视口下越小。

// 默认为0,在上面我们设置了视锥体的近平面距离是1,视角是35度。如果不移动摄像机,就无法看到物体。如果移动的距离不够,就看不到物体的全貌。如果距离太远,物体就变成很小的一点了。

cameraFrame.MoveForward(-15.0f);

// 设置三个顶点数据

GLfloat vCoast[9] = {

3,3,0,

0,3,0,

3,0,0

};

// 用点的形式

pointBatch.Begin(GL_POINTS, 3);

pointBatch.CopyVertexData3f(vCoast);

pointBatch.End();

// 为了流程清晰,其他图形顶点的设置,参见文末完整代码,此处省略

}

五、设置渲染参数

// 相机(观察者)角色帧

GLFrame cameraFrame;

// 对象角色帧

GLFrame objectFrame;

// 召唤场景

voidRenderScene(void)

{

// Clear the window with current clearing color

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

// 压栈: 创建一个新的矩阵,用来变换,不影响原始值,后续我们还要切换其他图形。

modelViewMatrix.PushMatrix();

M3DMatrix44f mCamera;

cameraFrame.GetCameraMatrix(mCamera);

// 栈顶上的单元矩阵 * 摄像机矩阵 = newMatrix

modelViewMatrix.MultMatrix(mCamera);

M3DMatrix44f mObjectFrame;

// 只要使用 GetMatrix 函数就可以获取矩阵堆栈顶部的值,这个函数可以进行2次重载。用来使用 GLShaderManager 的使用。或者是获取顶部矩阵的顶点副本数据

objectFrame.GetMatrix(mObjectFrame);

// 栈顶上的 newMatrix * 对象矩阵 = newMatrix

modelViewMatrix.MultMatrix(mObjectFrame);

/* GLShaderManager 中的Uniform 值——平面着色器

参数1:平面着色器

参数2:运行为几何图形变换指定一个 4 * 4变换矩阵

--transformPipeline.GetModelViewProjectionMatrix() 获取的

GetMatrix函数就可以获得矩阵堆栈顶部的值

参数3:颜色值(黑色)

*/

/*

transformPipeline 存储了 &modelViewMatrix、&projectionMatrix。调用 GetModelViewProjectionMatrix 函数,会取出最新的值进行矩阵变换,得到一个 模型视图投影矩阵(mvp)

*/

shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);

switch(nStep) {

case0:

//设置点的大小

glPointSize(4.0f);

pointBatch.Draw();

glPointSize(1.0f);

break;

// case 1,2,3 类似 case 0, 此处省略,参见文末完整代码

case4:

DrawWireFramedBatch(&triangleBatch);

break;

// case 5,6 类似 case 4,此处省略,参见文末完整代码

}

// 渲染参数已经设置完毕,清除栈顶的矩阵

modelViewMatrix.PopMatrix();

// 进行缓冲区交换

glutSwapBuffers();

}

// 除了平面绘制,增加了边框绘制,不然看不清图片拼接

voidDrawWireFramedBatch(GLBatch* pBatch)

{

/*------------画绿色部分----------------*/

/* GLShaderManager 中的Uniform 值——平面着色器

参数1:平面着色器

参数2:运行为几何图形变换指定一个 4 * 4变换矩阵

--transformPipeline 变换管线(指定了2个矩阵堆栈)

参数3:颜色值

*/

shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);

pBatch->Draw();

/*-----------边框部分-------------------*/

/*

glEnable(GLenum mode); 用于启用各种功能。功能由参数决定

参数列表:http://blog.csdn.net/augusdi/article/details/23747081

注意:glEnable() 不能写在glBegin() 和 glEnd()中间

GL_POLYGON_OFFSET_LINE 根据函数glPolygonOffset的设置,启用线的深度偏移

GL_LINE_SMOOTH 执行后,过虑线点的锯齿

GL_BLEND 启用颜色混合。例如实现半透明效果

GL_DEPTH_TEST 启用深度测试 根据坐标的远近自动隐藏被遮住的图形(材料

glDisable(GLenum mode); 用于关闭指定的功能 功能由参数决定

*/

//画黑色边框

glPolygonOffset(-1.0f, -1.0f);// 偏移深度,在同一位置要绘制填充和边线,会产生z冲突,所以要偏移

glEnable(GL_POLYGON_OFFSET_LINE);

// 画反锯齿,让黑边好看些

glEnable(GL_LINE_SMOOTH);

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//绘制线框几何黑色版 三种模式,实心,边框,点,可以作用在正面,背面,或者两面

//通过调用glPolygonMode将多边形正面或者背面设为线框模式,实现线框渲染

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

//设置线条宽度

glLineWidth(2.5f);

/* GLShaderManager 中的Uniform 值——平面着色器

参数1:平面着色器

参数2:运行为几何图形变换指定一个 4 * 4变换矩阵

--transformPipeline.GetModelViewProjectionMatrix() 获取的

GetMatrix函数就可以获得矩阵堆栈顶部的值

参数3:颜色值(黑色)

*/

shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);

pBatch->Draw();

// 复原原本的设置

//通过调用glPolygonMode将多边形正面或者背面设为全部填充模式

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glDisable(GL_POLYGON_OFFSET_LINE);

glLineWidth(1.0f);

glDisable(GL_BLEND);

glDisable(GL_LINE_SMOOTH);

}

注意:矩阵变换的时候,必须先乘上观察者矩阵,然后再乘对象矩阵。矩阵没有交换律,必须先明确观察者,对象矩阵的变换才是正确的,否则就是刻舟求剑。

GLFrame 角色帧,是拿来做变化用的。可以用来产生模型视图矩阵。来产生位置的移动。本案例用到了相机(观察者)角色帧和对象角色帧
GLTools-GLFrame概念

矩阵变换流程图

完整代码

#include"GLTools.h"

#include"GLMatrixStack.h"

#include"GLFrame.h"

#include"GLFrustum.h"

#include"GLBatch.h"

#include"GLGeometryTransform.h"

#include<math.h>

#ifdef __APPLE__

#include<glut/glut.h>

#else

#define FREEGLUT_STATIC

#include<GL/glut.h>

#endif

/*

GLMatrixStack 变化管线使用矩阵堆栈

GLMatrixStack 构造函数允许指定堆栈的最大深度、默认的堆栈深度为64.这个矩阵堆在初始化时已经在堆栈中包含了单位矩阵。

GLMatrixStack::GLMatrixStack(int iStackDepth = 64);

//通过调用顶部载入这个单位矩阵

void GLMatrixStack::LoadIndentiy(void);

//在堆栈顶部载入任何矩阵

void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);

*/

// 各种需要的类

GLShaderManager shaderManager;

GLMatrixStack modelViewMatrix;

GLMatrixStack projectionMatrix;

GLFrame cameraFrame;

GLFrame objectFrame;

//投影矩阵

GLFrustum viewFrustum;

//容器类(7种不同的图元对应7种容器对象)

GLBatch pointBatch;

GLBatch lineBatch;

GLBatch lineStripBatch;

GLBatch lineLoopBatch;

GLBatch triangleBatch;

GLBatch triangleStripBatch;

GLBatch triangleFanBatch;

//几何变换的管道

GLGeometryTransform transformPipeline;

GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };

GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };

// 跟踪效果步骤

int nStep = 0;

// 窗口已更改大小,或刚刚创建。无论哪种情况,我们都需要

// 使用窗口维度设置视口和投影矩阵.

voidChangeSize(int w, int h)

{

glViewport(0, 0, w, h);

//创建投影矩阵,并将它载入投影矩阵堆栈中

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

projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());

//调用顶部载入单元矩阵

modelViewMatrix.LoadIdentity();

}

// 此函数在呈现上下文中进行任何必要的初始化。.

// 这是第一次做任何与opengl相关的任务。

voidSetupRC()

{

// 灰色的背景

glClearColor(0.7f, 0.7f, 0.7f, 1.0f );

shaderManager.InitializeStockShaders();

glEnable(GL_DEPTH_TEST);

//设置变换管线以使用两个矩阵堆栈,存储不是值,是指针,当这两个矩阵重新复制,变换管线读到的值也会变化

transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

cameraFrame.MoveForward(-15.0f);

/*

常见函数:

void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);

参数1:表示使用的图元

参数2:顶点数

参数3:纹理坐标(可选)

//负责顶点坐标

void GLBatch::CopyVertexData3f(GLFloat *vNorms);

//结束,表示已经完成数据复制工作

void GLBatch::End(void);

*/

//定义一些点,三角形形状。

GLfloat vCoast[9] = {

3,3,0,0,3,0,3,0,0

};

//用点的形式

pointBatch.Begin(GL_POINTS, 3);

pointBatch.CopyVertexData3f(vCoast);

pointBatch.End();

//通过线的形式

lineBatch.Begin(GL_LINES, 3);

lineBatch.CopyVertexData3f(vCoast);

lineBatch.End();

//通过线段的形式

lineStripBatch.Begin(GL_LINE_STRIP, 3);

lineStripBatch.CopyVertexData3f(vCoast);

lineStripBatch.End();

//通过线环的形式

lineLoopBatch.Begin(GL_LINE_LOOP, 3);

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

};

// GLfloat vPyramid[12][3] = {

// -4.0f, 0.0f, -4.0f,

// 4.0f, 0.0f, -4.0f,

// 0.0f, 8.0f, 0.0f,

//

// 4.0f, 0.0f, -4.0f,

// 4.0f, 0.0f, 4.0f,

// 0.0f, 8.0f, 0.0f,

//

// 4.0f, 0.0f, 4.0f,

// -4.0f, 0.0f, 4.0f,

// 0.0f, 8.0f, 0.0f,

//

// -4.0f, 0.0f, 4.0f,

// -4.0f, 0.0f, -4.0f,

// 0.0f, 8.0f, 0.0f};

//GL_TRIANGLES 每3个顶点定义一个新的三角形

triangleBatch.Begin(GL_TRIANGLES, 12);

triangleBatch.CopyVertexData3f(vPyramid);

triangleBatch.End();

// 三角形扇形--六边形

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) {

//数组下标自增(每自增1次就表示一个顶点)

nVerts++;

/*

弧长=半径*角度,这里的角度是弧度制,不是平时的角度制

既然知道了cos值,那么角度=arccos,求一个反三角函数就行了

*/

//x点坐标 cos(angle) * 半径

vPoints[nVerts][0] = float(cos(angle)) * r;

//y点坐标 sin(angle) * 半径

vPoints[nVerts][1] = float(sin(angle)) * r;

//z点的坐标

vPoints[nVerts][2] = -1.5f;

}

// 结束扇形 前面一共绘制7个顶点(包括圆心)

//添加闭合的终点

//课程添加演示:屏蔽177-180行代码,并把绘制节点改为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();

//三角形条带,一个小环或圆柱段

//顶点下标

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++;

}

// 关闭循环

printf("三角形带的顶点数:%dn",iCounter);

//结束循环,在循环位置生成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();

}

// 除了平面绘制,增加了边框绘制,不然看不清图片拼接

voidDrawWireFramedBatch(GLBatch* pBatch)

{

/*------------画绿色部分----------------*/

/* GLShaderManager 中的Uniform 值——平面着色器

参数1:平面着色器

参数2:运行为几何图形变换指定一个 4 * 4变换矩阵

--transformPipeline 变换管线(指定了2个矩阵堆栈)

参数3:颜色值

*/

shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);

pBatch->Draw();

/*-----------边框部分-------------------*/

/*

glEnable(GLenum mode); 用于启用各种功能。功能由参数决定

参数列表:http://blog.csdn.net/augusdi/article/details/23747081

注意:glEnable() 不能写在glBegin() 和 glEnd()中间

GL_POLYGON_OFFSET_LINE 根据函数glPolygonOffset的设置,启用线的深度偏移

GL_LINE_SMOOTH 执行后,过虑线点的锯齿

GL_BLEND 启用颜色混合。例如实现半透明效果

GL_DEPTH_TEST 启用深度测试 根据坐标的远近自动隐藏被遮住的图形(材料

glDisable(GLenum mode); 用于关闭指定的功能 功能由参数决定

*/

//画黑色边框

glPolygonOffset(-1.0f, -1.0f);// 偏移深度,在同一位置要绘制填充和边线,会产生z冲突,所以要偏移

glEnable(GL_POLYGON_OFFSET_LINE);

// 画反锯齿,让黑边好看些

glEnable(GL_LINE_SMOOTH);

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//绘制线框几何黑色版 三种模式,实心,边框,点,可以作用在正面,背面,或者两面

//通过调用glPolygonMode将多边形正面或者背面设为线框模式,实现线框渲染

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

//设置线条宽度

glLineWidth(2.5f);

/* GLShaderManager 中的Uniform 值——平面着色器

参数1:平面着色器

参数2:运行为几何图形变换指定一个 4 * 4变换矩阵

--transformPipeline.GetModelViewProjectionMatrix() 获取的

GetMatrix函数就可以获得矩阵堆栈顶部的值

参数3:颜色值(黑色)

*/

shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);

pBatch->Draw();

// 复原原本的设置

//通过调用glPolygonMode将多边形正面或者背面设为全部填充模式

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glDisable(GL_POLYGON_OFFSET_LINE);

glLineWidth(1.0f);

glDisable(GL_BLEND);

glDisable(GL_LINE_SMOOTH);

}

// 召唤场景

voidRenderScene(void)

{

// Clear the window with current clearing color

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

//压栈

modelViewMatrix.PushMatrix();

M3DMatrix44f mCamera;

cameraFrame.GetCameraMatrix(mCamera);

//矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部

modelViewMatrix.MultMatrix(mCamera);

M3DMatrix44f mObjectFrame;

//只要使用 GetMatrix 函数就可以获取矩阵堆栈顶部的值,这个函数可以进行2次重载。用来使用GLShaderManager 的使用。或者是获取顶部矩阵的顶点副本数据

objectFrame.GetMatrix(mObjectFrame);

//矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部

modelViewMatrix.MultMatrix(mObjectFrame);

/* GLShaderManager 中的Uniform 值——平面着色器

参数1:平面着色器

参数2:运行为几何图形变换指定一个 4 * 4变换矩阵

--transformPipeline.GetModelViewProjectionMatrix() 获取的

GetMatrix函数就可以获得矩阵堆栈顶部的值

参数3:颜色值(黑色)

*/

shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);

switch(nStep) {

case0:

//设置点的大小

glPointSize(4.0f);

pointBatch.Draw();

glPointSize(1.0f);

break;

case1:

//设置线的宽度

glLineWidth(2.0f);

lineBatch.Draw();

glLineWidth(1.0f);

break;

case2:

glLineWidth(2.0f);

lineStripBatch.Draw();

glLineWidth(1.0f);

break;

case3:

glLineWidth(2.0f);

lineLoopBatch.Draw();

glLineWidth(1.0f);

break;

case4:

DrawWireFramedBatch(&triangleBatch);

break;

case5:

DrawWireFramedBatch(&triangleStripBatch);

break;

case6:

DrawWireFramedBatch(&triangleFanBatch);

break;

}

//还原到以前的模型视图矩阵(单位矩阵)

modelViewMatrix.PopMatrix();

// 进行缓冲区交换

glutSwapBuffers();

}

//特殊键位处理(上、下、左、右移动)

voidSpecialKeys(int key, int x, int y)

{

if(key == GLUT_KEY_UP)

//围绕一个指定的X,Y,Z轴旋转。

objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);

if(key == GLUT_KEY_DOWN)

objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);

if(key == GLUT_KEY_LEFT)

objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);

if(key == GLUT_KEY_RIGHT)

objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);

glutPostRedisplay();

}

//根据空格次数。切换不同的“窗口名称”

voidKeyPressFunc(unsignedchar key, int x, int y)

{

if(key == 32)

{

nStep++;

if(nStep > 6)

nStep = 0;

}

switch(nStep)

{

case0:

glutSetWindowTitle("GL_POINTS");

break;

case1:

glutSetWindowTitle("GL_LINES");

break;

case2:

glutSetWindowTitle("GL_LINE_STRIP");

break;

case3:

glutSetWindowTitle("GL_LINE_LOOP");

break;

case4:

glutSetWindowTitle("GL_TRIANGLES");

break;

case5:

glutSetWindowTitle("GL_TRIANGLE_STRIP");

break;

case6:

glutSetWindowTitle("GL_TRIANGLE_FAN");

break;

}

glutPostRedisplay();

}

intmain(int argc, char* argv[])

{

gltSetWorkingDirectory(argv[0]);

glutInit(&argc, argv);

//申请一个颜色缓存区、深度缓存区、双缓存区、模板缓存区

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);

//设置window 的尺寸

glutInitWindowSize(800, 600);

//创建window的名称

glutCreateWindow("GL_POINTS");

//注册回调函数(改变尺寸)

glutReshapeFunc(ChangeSize);

//点击空格时,调用的函数

glutKeyboardFunc(KeyPressFunc);

//特殊键位函数(上下左右)

glutSpecialFunc(SpecialKeys);

//显示函数

glutDisplayFunc(RenderScene);

//判断一下是否能初始化glew库,确保项目能正常使用OpenGL 框架

GLenum err = glewInit();

if (GLEW_OK != err) {

fprintf(stderr, "GLEW Error: %sn", glewGetErrorString(err));

return1;

}

//绘制

SetupRC();

//runloop运行循环

glutMainLoop();

return0;

}

以上是 OpenGL 基本图元绘制案例及解析 的全部内容, 来源链接: utcz.com/a/31771.html

回到顶部