一、目标结果
二、分析过程
分析流程简图如下
三、全部代码如下:
下面从main.cpp 的流水线讲解整个实现过程
3.1 准备工作
3.1.1 设置当前工作目录
gltSetWorkingDirectory(argv[0]);
其中argv
源自int main(int argc,char *argv[]){}
函数的参数
3.1.2 初始化GLUT的库
glutInit(&argc, argv);
3.1.3 初始化双缓冲区
初始化双缓冲窗口,其中标志GLUT_DOUBLE、GLUT_RGBA、GLUT_DEPTH、GLUT_STENCIL分别指双缓冲窗口、RGBA颜色模式、深度测试、模板缓冲区
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
3.1.4 配置GLUT 窗口
glutInitWindowSize(300, 300); // 初始化窗口
glutCreateWindow("Triangle"); // 配置创建窗口名
3.2 GLUT 内部循环
3.2.1 注册重塑函数
glutReshapeFunc(changeSize);
ChangeSize函数,主要作用是窗口大小改变是,接收新的宽度和高度,实现如下:
void changeSize(int w,int h)
{
/*
x,y 参数代表窗口中视图的左下角坐标,而宽度、高度是像素为表示,通常x,y 都是为0
*/
glViewport(0, 0, w, h);
}
3.2.2 注册显示函数(渲染)
glutDisplayFunc(RenderScene);
有以下步骤
清理一个或一组特定的缓冲区
- GL_COLOR_BUFFER_BIT :指示当前激活的用来进行颜色写入缓冲区
- GL_DEPTH_BUFFER_BIT :指示深度缓存区
- GL_STENCIL_BUFFER_BIT:指示模板缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
设置一组浮点数来表示红色
GLfloat vRed[] = {1.0,0.0,0.0,1.0f};
传递到存储着色器
shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
提交着色器
triangleBatch.Draw();
交换缓冲区:这里主要是讲后台缓冲区进行渲染,结束后把图像结果交给前台
glutSwapBuffers();
3.2.3 注册特殊函数(键位移动)
glutSpecialFunc(SpecialKeys);
其实这里的键位比较简单,主要步骤如下:
设置按键每次移动的步长
GLfloat stepSize = 0.25f;
配置移动起始X, Y坐标,
GLfloat blockX = vVerts[0]; GLfloat blockY = vVerts[10];
移动后X,Y坐标,这里主要判断key
if (key == GLUT_KEY_UP) { blockY += stepSize; } if (key == GLUT_KEY_DOWN) { blockY -= stepSize; } if (key == GLUT_KEY_LEFT) { blockX -= stepSize; } if (key == GLUT_KEY_RIGHT) { blockX += stepSize; }
边界碰撞的配置(碰撞后返回)
碰到最左边
if (blockX < -1.0f) { blockX = -1.0f; }
碰到最右边
//1.0 - blockSize * 2 = 总边长 - 正方形的边长 = 最左边点的位置 if (blockX > (1.0 - blockSize * 2)) { blockX = 1.0f - blockSize * 2; }
碰到最下边
//-1.0 - blockSize * 2 = Y(负轴边界) - 正方形边长 = 最下面点的位置 if (blockY < -1.0f + blockSize * 2 ) { blockY = -1.0f + blockSize * 2; }
碰到最顶边
if (blockY > 1.0f) { blockY = 1.0f; }
重新计算所有顶点
vVerts[0] = blockX; vVerts[1] = blockY - blockSize*2; printf("(%f,%f)\n",vVerts[0],vVerts[1]); vVerts[3] = blockX + blockSize*2; vVerts[4] = blockY - blockSize*2; printf("(%f,%f)\n",vVerts[3],vVerts[4]); vVerts[6] = blockX + blockSize*2; vVerts[7] = blockY; printf("(%f,%f)\n",vVerts[6],vVerts[7]); vVerts[9] = blockX; vVerts[10] = blockY; printf("(%f,%f)\n",vVerts[9],vVerts[10]);
添加顶点到缓冲区
triangleBatch.CopyVertexData3f(vVerts);
通知重新渲染
glutPostRedisplay();
3.3 GLUEW 库安全
初始化一个GLEW库,确保OpenGL API对程序完全可用
GLenum status = glewInit();
if (GLEW_OK != status) {
printf("GLEW Error:%s\n",glewGetErrorString(status));
return 1;
}
3.4 配置渲染环境
setupRC();
3.4.1 设置清屏颜色
其实也是设置当前窗口的背景色
glClearColor(0.98f, 0.80f, 0.7f, 1);
3.4.2 初始化固定着色器
shaderManager.InitializeStockShaders();
3.4.3 顶点连接类型配置和提交缓冲区
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();
3.5 添加到任务的 loop
glutMainLoop();
3.6 总流程main 的步骤
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
glutInitWindowSize(300, 300);
glutCreateWindow("Triangle");
//注册重塑函数
glutReshapeFunc(changeSize);
//注册显示函数
glutDisplayFunc(RenderScene);
//注册特殊函数
glutSpecialFunc(SpecialKeys);
GLenum status = glewInit();
if (GLEW_OK != status) {
printf("GLEW Error:%s\n",glewGetErrorString(status));
return 1;
}
setupRC();
glutMainLoop();
四、小结
这篇文章,简单的介绍了,在特定色彩下,绘制一个正方形,并且通过按键移动它,可以见到,OpenGL 语句还是相当的见解。