一、准备工作
在绘制正方形之前我们首先来了解一下,代码的执行过程中用到的几个方法:
二、开始绘制正方形
首先设置正方形的4个顶点
GLfloatvVerts[] = {
-blockSize,-blockSize,0.0f,
blockSize,-blockSize,0.0f,
blockSize,blockSize,0.0f,
-blockSize,blockSize,0.0f
};
设置边长
GLfloat blockSize = 0.1f;
1、然后来到我们的main函数中,看看需要执行的操作
gltSetWorkingDirectory(argv[0]); //设置当前工作目录,针对MAC OS X
初始化GLUT库
glutInit(&argc, argv); //这个函数只是传输命令参数并且初始化glut库
初始化双缓冲窗口
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL); //GLUT_DOUBLE:双缓存窗口,是指绘图命令实际上是离屏缓存区执行的,然后迅速转换成窗口视图,这种方式,经常用来生成动画效果;
//GLUT_RGBA:RGBA颜色模式
//GLUT_DEPTH:深度测试,标志将一个深度缓存区分配为显示的一部分,因此我们能够执行深度测试;
//GLUT_STENCIL:模板缓冲区,确保我们也会有一个可用的模板缓存区。
设置窗口大小、窗口标题:
glutInitWindowSize(500, 500);
glutCreateWindow("Triangle");
之后我们来注册两个回调函数:
//注册重塑函数,这个函数是为窗口改变大小而设置的一个回调函数
glutReshapeFunc(changeSize);
//注册显示函数,这个函数是OpenGL 渲染的回调函数
glutDisplayFunc(RenderScene);
然后初始化一个GLEW库,确保OpenGL API对程序完全可用。
GLenumstatus =glewInit();
if(GLEW_OK!= status) {
printf("GLEW Error:%s\n",glewGetErrorString(status));
return1;
}
设置我们的渲染环境
setupRC();
最后我们设置一下glutMainLoop();这个函数
glutMainLoop这个函数是进入GLUT事件处理循环。在一个GLUT程序中,这个例程被调用一次 。一旦被调用,这个程序将永远不会返回 。它将调用必要的任何已注册回调。这个函数就类似于iOS中的RunLoop循环。
至此main函数中的工作就做完了。
2、setupRC()中的操作
设置清屏颜色(背景颜色)
glClearColor(0.98f, 0.40f, 0.7f, 1);
使用固定管线进行渲染
shaderManager.InitializeStockShaders();
如果没有着色器,在OpenGL 核心框架中是无法进行任何渲染的。在这个我们使用固定管线渲染.
设置绘制时使用的图元及顶点个数.
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
GL_TRIANGLE_FAN是OpenGL中的一种图元,它是以一个顶点为中心,呈扇形排列,共用相邻的两个顶点的三角形扇。
以下是OpenGL中的7中基本图元:
triangleBatch.CopyVertexData3f(vVerts); //设置顶点
triangleBatch.End();//结束
3、changeSize(int w,int h)函数
glViewport(0,0, w, h); 这里是设置视口的位置大小。
4、RenderScene()函数
清除一个或者一组特定的缓存区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
GL_COLOR_BUFFER_BIT :指示当前激活的用来进行颜色写入缓冲区
GL_DEPTH_BUFFER_BIT :指示深度缓存区
GL_STENCIL_BUFFER_BIT:指示模板缓冲区
渲染颜色
GLfloatvRed[] = {1.0,0.0,0.0,1.0f}; //设置颜色值
shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed); //设置使用GLT_SHADER_IDENTITY(单元着色器),并传入设置的颜色
提交着色器
triangleBatch.Draw();
交换缓冲区
glutSwapBuffers();
再开始时我们设置了一个双缓冲的渲染环境。这意味着将在后台缓冲区进行渲染,渲染结束后交换给前台。这种方式可以防止观察者看到可能伴随着动画帧与动画帧之间的闪烁的渲染过程。缓冲区交换平台将以平台特定的方式进行。
到这里为止我们就能画出一个正方形了,效果图如下:
三、绘制完正方形后我们要让他能移动。这里有两种方式:1、更新每个顶点的坐标。2、利用矩阵。
不管用哪种方式,首先我们在main函数中注册一下glutSpecialFunc(SpecialKeys)这个函数。当我们使用特殊键位时就会调用这个函数,我们这里是使用上下左右键来移动正方形。
1、更新坐标
在SpecialKeys这个函数中我们要:
·首先需要定义一个步长。
·选定一个顶点来进行计算。这里选定D点
·设定使用到的键位。这里使用上(GLUT_KEY_UP)、下(GLUT_KEY_DOWN)、左(GLUT_KEY_LEFT)、右(GLUT_KEY_RIGHT)
·进行边界碰撞检测,不然会移出屏幕之外。
实现代码如下:
void SpecialKeys(intkey,intx,inty){
//在这个函数中计算x轴、y轴移动的距离、以及进行碰撞检测
GLfloat stepSize =0.025f;
GLfloat blockX =vVerts[0];
GLfloat blockY =vVerts[10];
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;
}
//触碰到边界(4个边界)的处理
//当正方形移动超过最左边的时候
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;
}
// Recalculate vertex positions
vVerts[0] = blockX;
vVerts[1] = blockY -blockSize*2;
vVerts[3] = blockX +blockSize*2;
vVerts[4] = blockY -blockSize*2;
vVerts[6] = blockX +blockSize*2;
vVerts[7] = blockY;
vVerts[9] = blockX;
vVerts[10] = blockY;
//提交新的顶点数据
triangleBatch.CopyVertexData3f(vVerts);
//重新渲染
glutPostRedisplay();
}
2、矩阵方式
·设置两个全局变量,记录x轴、y轴的平移距离
GLfloat xPos = 0.0f;
GLfloat yPos = 0.0f;
·在SpecialKeys函数中计算,向不同方向移动时移动的距离。
·在RenderScene修改为用矩阵的方式去绘制
代码实现如下:
voidSpecialKeys(intkey,intx,inty){
GLfloatstepSize =0.025f;
if(key ==GLUT_KEY_UP) {
yPos+= stepSize;
}
if(key ==GLUT_KEY_DOWN) {
yPos-= stepSize;
}
if(key ==GLUT_KEY_LEFT) {
xPos-= stepSize;
}
if(key ==GLUT_KEY_RIGHT) {
xPos+= stepSize;
}
//碰撞检测
if(xPos< (-1.0f+blockSize)) {
xPos= -1.0f+blockSize;
}
if(xPos> (1.0f-blockSize)) {
xPos=1.0f-blockSize;
}
if(yPos< (-1.0f+blockSize)) {
yPos= -1.0f+blockSize;
}
if(yPos> (1.0f-blockSize)) {
yPos=1.0f-blockSize;
}
glutPostRedisplay();
}
//修改RenderScene的渲染方式
void RenderScene(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0f,0.0f,0.0f,0.0f};
//定义一个平移矩阵
M3DMatrix44f mTransfromMatrix;
//获得平移后的矩阵
m3dTranslationMatrix44(mTransfromMatrix, xPos, yPos, 0.0f);
//将矩阵结果 提交给固定着色器(平面着色器)中绘制
shaderManager.UseStockShader(GLT_SHADER_FLAT,mFinalTransform,vRed);
triangleBatch.Draw();
glutSwapBuffers();
}
这样就能使用上下左右键位来控制正方形的移动了。