前面代码1~代码5的学习和效果,主要是绘制平面图形,那么通过这些知识,如何绘制3D图形呢,本文试图尝试使用目前掌握的知识,看看能不能绘制一些3D图形出来,尝试的手段是三个方面:
(1)顶点数组(2)批次设置中的图元参数的调整(3)glPolygonMode模式的调整
尝试1:关于顶点数组,绘制一个立体矩形需要确定8个顶点,以平视图的方式确定
尝试2:关于顶点数组,绘制一个立体矩形需要确定8个顶点,以画立体图形的方式确
尝试3:关于顶点数组,绘制一个立体矩形,相当于是由很多个面组成,每个面上相同位置上的点只是在z轴上的值不同而已;
尝试4:想起了平时在一张纸上画一个立体矩形的方式,让每个面都有个“错位”,类似于下图所示:
接下里就是依据上面想好的尝试用代码实现下,看看效果。
注意:需要在配置好OpenGL的编程环境中运行下列代码,环境配置文章可参考:
OpenGL在Mac项目上的配置
下面的代码,直接放置在main.cpp文件中即可:
#pragma mark - 尝试用现有的知识画一个立体矩形
#include "GLTools.h"
#include "GLBatch.h"
#include <math.h>
#include <glut/glut.h>
GLShaderManager shaderManager;
//批次
GLBatch triangleFanBatch;
//绿色
GLfloat vGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
//黑色
GLfloat vBlack[] = {0.0f, 0.0f, 0.0f, 1.0f};
//初始化三角形扇批次
void SetupTriangleFanBatch() {
// 以平视图的方式描出矩形的8个顶点
GLfloat vVerts1[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 1.0f,
0.5f, -0.5f, 1.0f,
0.5f, 0.5f, 1.0f,
-0.5f, 0.5f, 1.0f,
};
// 以画立体图形的方式描出矩形的8个顶点
GLfloat vVerts2[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
-0.4f, -0.4f, 0.0f,
0.6f, -0.4f, 0.0f,
0.6f, 0.6f, 0.0f,
-0.4f, 0.6f, 0.0f,
};
// 以平视图的方式构建顶点数据
GLfloat vVerts3[1000][3];
for (int i = 0; i < 1000; i++) {
GLfloat stepNum = 0.3 / 1000;
if (i % 4 == 0) {
vVerts3[i][0] = -0.5f;
vVerts3[i][1] = -0.5f;
vVerts3[i][2] = -0.5f + stepNum * i;
}
if (i % 4 == 1) {
vVerts3[i][0] = 0.5f;
vVerts3[i][1] = -0.5f;
vVerts3[i][2] = -0.5f + stepNum * i;
}
if (i % 4 == 2) {
vVerts3[i][0] = 0.5f;
vVerts3[i][1] = 0.5f;
vVerts3[i][2] = -0.5f + stepNum * i;
}
if (i % 4 == 3) {
vVerts3[i][0] = -0.5f;
vVerts3[i][1] = 0.5f;
vVerts3[i][2] = -0.5f + stepNum * i;
}
}
// 以画立体图形的方式构建顶点数据
GLfloat vVerts4[1000][3];
for (int i = 0; i < 1000; i++) {
GLfloat stepNum = 0.3 / 1000;
if (i % 4 == 0) {
vVerts4[i][0] = -0.5f + stepNum * i;
vVerts4[i][1] = -0.5f + stepNum * i;
vVerts4[i][2] = -0.5f + stepNum * i;
}
if (i % 4 == 1) {
vVerts4[i][0] = 0.5f + stepNum * i;
vVerts4[i][1] = -0.5f + stepNum * i;
vVerts4[i][2] = -0.5f + stepNum * i;
}
if (i % 4 == 2) {
vVerts4[i][0] = 0.5f + stepNum * i;
vVerts4[i][1] = 0.5f + stepNum * i;
vVerts4[i][2] = -0.5f + stepNum * i;
}
if (i % 4 == 3) {
vVerts4[i][0] = -0.5f + stepNum * i;
vVerts4[i][1] = 0.5f + stepNum * i;
vVerts4[i][2] = -0.5f + stepNum * i;
}
}
//三角形扇批次初始化
/*
GL_POINTS: 点
GL_LINES: 线
GL_LINE_STRIP: 条带线
GL_LINE_LOOP: 循环线
GL_TRIANGLES: 独立三角形
GL_TRIANGLE_STRIP: 三角形条带
GL_TRIANGLE_FAN: 三角形扇面
*/
triangleFanBatch.Begin(GL_POINTS, 8);
triangleFanBatch.CopyVertexData3f(vVerts2);
triangleFanBatch.End();
glPointSize(8.0f);
}
//为程序作一次性的设置
void SetupRC() {
//设置窗口背景颜色
glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
//初始化着色器管理器
shaderManager.InitializeStockShaders();
//准备三角形扇批次
SetupTriangleFanBatch();
}
//画三角形
void DrawTriangleBatch(GLBatch* pBatch) {
//多边形模式切换为前后面的线模式
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//画边界黑线
glLineWidth(2.5f);
pBatch->Draw();
}
//渲染画面
void RenderScene(void) {
//清除一个或一组特定的缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// 传递到存储着色器,即GLT_SHADER_IDENTITY着色器,这个着色器只是使用指定颜色以默认笛卡尔坐标系在屏幕上渲染几何图形
// 利用单位着色器设置矩形颜色
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vGreen);
//画图
DrawTriangleBatch(&triangleFanBatch);
//将在后台缓冲区进行渲染,然后在结束时交换到前台
glutSwapBuffers();
}
//窗口大小改变时接受新的宽度和高度
void ChangeSize(int width, int height) {
// 防止下面除法的除数为0导致的闪退
if(height == 0) height = 1;
//设置视图窗口位置
glViewport(0, 0, width, height);
}
//程序入口
int main(int argc, char* argv[]) {
//设置当前工作目录,针对MAC OS X
gltSetWorkingDirectory(argv[0]);
//初始化GLUT库
glutInit(&argc, argv);
/*初始化渲染模式,其中标志GLUT_DOUBLE、GLUT_RGBA、GLUT_DEPTH、GLUT_STENCIL分别指
双缓冲窗口、RGBA颜色模式、深度测试、模板缓冲区*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
//初始化窗口大小
glutInitWindowSize(800, 720);
//创建窗口
glutCreateWindow("GL_POINTS");
//注册回调函数
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
//确保驱动程序的初始化中没有出现任何问题
GLenum err = glewInit();
if(GLEW_OK != err) {
fprintf(stderr, "glew error:%s\n", glewGetErrorString(err));
return 1;
}
//初始化设置
SetupRC();
//进入调用循环
glutMainLoop();
return 0;
}
从这三个方面:(1)顶点数组(2)批次设置中的图元参数的调整(3)glPolygonMode模式的调整,形成的组合挺多的,本文只将比较有立体感的组合的效果图贴出来做个记录:
使用配置:
triangleFanBatch.Begin(GL_TRIANGLE_FAN, 1000);
triangleFanBatch.CopyVertexData3f(vVerts4);
triangleFanBatch.End();
的效果图如下:
这个图形还是有几分立体感的,毕竟把线条标记出来的话,显示的这样的:
这样也算是“静态的”3D图形,真正的3D图形还需要有的功能是要全角度观察、近距离远距离观察,角度和远近不一样看到的效果也会不一样。因此,结论就是,离真正的3D图形的绘制,还差距一些不知道的理论知识。