效果图如下所示:
问题:
图1:没有改变窗口大小下,正方形不能移动到最左边
图2:改变窗口大小下,正方形可以移动到最左边。
- 在没有改变窗口大小的情况下,不能移动到最左边。而改动窗口了就可以移动到了最左边。
问题解决:因为GLUT/GLTOOL和xcode版本不兼容
控制流程图
环境搭建:
环境搭建参考链接
绘制正方形
- 首先定义工具类:
///定义一个着色管理器
GLShaderManager shaderManager;
///简单的批次容器,是GTtools的一个简单的容器类
GLBatch triangleBatch;
- 定义顶点数组及边长:
//blockSize 边长
GLfloat blockSize = 0.1f;
///正方形的四个点坐标
GLfloat vVerts[] = {
-blockSize,blockSize,0.0f,
blockSize,blockSize,0.0f,
blockSize,-blockSize,0.0f,
-blockSize,-blockSize,0.0f
};
- 注册自定义changeSize、RenderScence、SpecialKeys函数:
glutDisplayFunc(RenderScence);
glutReshapeFunc(ChageSize);
glutSpecialFunc(SpecialKeys);
- 设置初始化函数并开启runloop:
SetupRC();
glutMainLoop();///类似IOS runLoop运行循环
- 自定义RenderScence函数
glutDisplayFunc(函数名)注册为显示渲染函数,当屏幕发生变化或者开发者主动渲染会调用此函数,用来实现数据的渲染(绘制)过程- 清除特定缓冲区,缓冲区是一块存在图像信息的储存空间,红色、绿色、蓝色和alpha分量通常一起分量通常一起作为颜色缓存区或像素缓存区引用。
OpenGL 中不止一种缓冲区(颜色缓存区、深度缓存区和模板缓存区)
清除缓存区对数值进行预置
参数:指定将要清除的缓存的
GL_COLOR_BUFFER_BIT
:指示当前激活的用来进行颜色写入缓冲区
GL_DEPTH_BUFFER_BIT
:指示深度缓存区
GL_STENCIL_BUFFER_BIT
:指示模板缓冲区 - 设置一组浮点数来表示颜色(即渲染的颜色),
- 顶点数据传递到存储着色器,
GLT_SHADER_IDENTITY
单元着色器 只是使用指定颜色以默认笛卡尔坐标第在屏幕上渲染几何图形, - 提交着色器进行绘制,
- 将后台缓冲区进行渲染,然后结束后交换给前台。
- 清除特定缓冲区,缓冲区是一块存在图像信息的储存空间,红色、绿色、蓝色和alpha分量通常一起分量通常一起作为颜色缓存区或像素缓存区引用。
void RenderScence(void) {
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();
}
- 自定义changeSize函数
glutReshaperFunc
(函数名),注册为重塑函数,当屏幕大小发生变化/或者第一次创建窗口时。
回调用changeSize
函数调整窗口大小、视口大小
处理业务:
1、设置OpenGL
视口 2、设置OpenGL
投影方式等
void ChageSize(int w,int h){
glViewport(0, 0, w, h);
}
- 自定义SetupRC函数
自定义函数,设置需要渲染的图形的相关顶点数据,颜色数据等数据准备工作
处理业务:
1、设置窗口背景颜色
2、初始化存储着色器shaderManger
3、设置图像顶点数据,GL_TRIANGLE_FAN
:以⼀一个圆点为中⼼心呈扇形排列列,共⽤用相邻顶点的一组三⻆角形
4、利用三角形批次类将数据传递到着色器中
void SetupRC(){
glClearColor(0.38f, 0.62f, 0.5f, 1.0f);
shaderManager.InitializeStockShaders();
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();
}
特殊键位控制效果
首先需要先知道顶点数据是在坐标系上的哪个位置,如以上我们的点在坐标系中的位置如下:
其次我们定义好
blockSize
即顶点到中心的位置,则正方形边长为blockSize*2
。
- 重点——注册SpecialKeys函数
- 定义步长
- 选择好一个顶点作为移动的起始点
- 上下左右键位移动处理
- 发现移动时可以移出窗口外,故进行窗口边缘检测
- 更新顶点数据、重新提交渲染
具体实现如下:
void SpecialKeys(int key ,int x ,int y){
GLfloat stepSize = 0.025f;
GLfloat blockX = vVerts[3];
GLfloat blockY = vVerts[4];
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.0) {
blockX = 1.0;
}
if (blockX < -1.0 + 2 * blockSize) {
blockX = -1.0 +2*blockSize;
}
if (blockY > 1.0) {
blockY = 1.0;
}
if (blockY < -1.0 + 2 * blockSize) {
blockY = -1.0 +2*blockSize;
}
vVerts[0] = blockX - blockSize * 2;
vVerts[1] = blockY;
vVerts[3] = blockX;
vVerts[4] = blockY;
vVerts[6] = blockX;
vVerts[7] = blockY-blockSize *2;
vVerts[9] = blockX - blockSize * 2;
vVerts[10] = blockY - blockSize * 2;
triangleBatch.CopyVertexData3f(vVerts);
glutPostRedisplay();
}
优化处理
如果顶点有很多的话,则我们需要计算每个顶点的坐标,需要写很多的计算代码,所以我们可以利用平移矩阵进行平移处理,则不需要计算每个顶点的坐标位置。平移矩阵可以理解为相对于正方形的中心点进行移动。
//记录移动图形时,在x轴上平移的距离
GLfloat xPos = 0.0f;
//记录移动图形时,在y轴上平移的距离
GLfloat yPos = 0.0f;
//记录移动的步长
GLfloat stepSize = 0.025f;
将SpecialKeys函数修改如下:
///特殊键位处理(上下左右移动)
void SpecialKeys(int key ,int x ,int y){
GLfloat stepSize = 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.0 - blockSize) {
xPos = 1.0 - blockSize;
}
if (xPos < -1.0 + blockSize) {
xPos = -1.0 + blockSize;
}
if (yPos > 1.0 - blockSize) {
yPos = 1.0 - blockSize;
}
if (yPos < -1.0 + blockSize) {
yPos = -1.0 + blockSize;
}
glutPostRedisplay();
}
我们需要修改RenderScence函数:
- 清除特定缓冲区,定义渲染画笔颜色
- 定义平移矩阵
- 顶点数据传递到存储着色器,
GLT_SHADER_FLAT
着色器 以一个圆点为中⼼心呈扇形排列列,共⽤用相邻顶点的一组三⻆角形 - 提交着色器进行绘制,
- 将后台缓冲区进行渲染,然后结束后交换给前台。
void RenderScence(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0,0.0,0.0,1.0f};
///定义矩阵
M3DMatrix44f mTransfromMatix;
///平移矩阵
m3dTranslationMatrix44(mTransfromMatix, xPos, yPos, 0.0);
shaderManager.UseStockShader(GLT_SHADER_FLAT,mTransfromMatix,vRed);
///4、提交着色器进行绘制
triangleBatch.Draw();
///5、将后台缓冲区进行渲染,然后结束后交换给前台
glutSwapBuffers();
}
至此优化完成。
完整代码见Github -OpenGLDemo02