iOS OpenGL ES2.0教程    Lesson03  旋转

注:可供翻译的课程只有前两课。从这节课起,我试着根据我对OpenGL ES的理解写接下去的课程,希望能和大家一起学习。

在上节课中,我们绘制了一个三角形。在这一课里,我们学习如何旋转。我们创建一个正方形,并让它沿Y轴旋转。

绘制一个长方形

首先,我们要在屏幕上绘制一个长方形,如下图所示:

要注意的是,在用OpenGL ES绘制图形的时候,是不能直接绘制矩形或其他多边形的,只能绘制三角形。所以,我们这里需要将通过绘制两个三角形来得到一个长方形。在图中分别绘制由顶点(0, 1, 2)和顶点(2, 3, 0)构成的三角形。

如果我们用上节课所使用的方法,每个三角形需要指定3个顶点的信息,那么两个三角形则需要指定6个顶点。这6个顶点中有重复的数据,实际上只需要指定4个不同的顶点就可以了。我们可以用新的方法来实现这个功能。在文件Lesson03.mm中:

  1. //---------------------------------------------------
  2. //create a rectangle
  3. std::vector<float> geometryData;
  4. //vertex 0, left/buttom
  5. geometryData.push_back(-0.5); geometryData.push_back(-0.5); geometryData.push_back(0.0); geometryData.push_back(1.0);
  6. // 1, right/buttom
  7. geometryData.push_back(0.5); geometryData.push_back(-0.5); geometryData.push_back(0.0); geometryData.push_back(1.0);
  8. // 2, right/ups
  9. geometryData.push_back(0.5); geometryData.push_back(0.5); geometryData.push_back(0.0); geometryData.push_back(1.0);
  10. // 3, left/up
  11. geometryData.push_back(-0.5); geometryData.push_back(0.5); geometryData.push_back(0.0); geometryData.push_back(1.0);
  12. //generate an ID for our geometry buffer in the video memory and make it the active one
  13. glGenBuffers(1, &m_geometryBuffer);
  14. glBindBuffer(GL_ARRAY_BUFFER, m_geometryBuffer);
  15. //send the data to the video memory
  16. glBufferData(GL_ARRAY_BUFFER, geometryData.size() * sizeof(float), &geometryData[0], GL_STATIC_DRAW);

指定4个顶点的数据,顶点按照添加的顺序,其索引值分别为0, 1, 2, 3。然后将顶点数据传送给OpenGL,和上一课用的方法一样。屏幕显示范围是从(-1, 1),中心点位置是(0, 0),所以 (0.5,0.5)指的是右上1/4屏幕的中间,其他点以此类推。

  1. //create a color buffer, to make our triangle look pretty
  2. std::vector<float> colorData;
  3. //3 floats define one color value (red, green and blue) with 0 no intensity and 1 full intensity
  4. //each color triplet is assigned to the vertex at the same position in the buffer, so first color -> first vertex
  5. //vertex 0 is red
  6. colorData.push_back(1.0); colorData.push_back(0.0); colorData.push_back(0.0);
  7. // 1 is blue
  8. colorData.push_back(0.0); colorData.push_back(0.0); colorData.push_back(1.0);
  9. // 2 is green
  10. colorData.push_back(0.0); colorData.push_back(1.0); colorData.push_back(0.0);
  11. // 3 is blue
  12. colorData.push_back(0.0); colorData.push_back(0.0); colorData.push_back(1.0);
  13. //generate an ID for the color buffer in the video memory and make it the active one
  14. glGenBuffers(1, &m_colorBuffer);
  15. glBindBuffer(GL_ARRAY_BUFFER, m_colorBuffer);
  16. //send the data to the video memory
  17. glBufferData(GL_ARRAY_BUFFER, colorData.size() * sizeof(float), &colorData[0], GL_STATIC_DRAW);

指定4个顶点的颜色,并将数据传递到VBO中。

  1. //create vertex indices
  2. std::vector<GLubyte> indexData;
  3. //3 byte define 1 triangle
  4. indexData.push_back(0); indexData.push_back(1); indexData.push_back(2);
  5. indexData.push_back(2); indexData.push_back(3); indexData.push_back(0);
  6. m_indexNumber = indexData.size();
  7. //generate an ID for the index buffer in video memory
  8. glGenBuffers(1, &m_indexBuffer);
  9. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
  10. //send data to video memory
  11. glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(GLubyte), &indexData[0], GL_STATIC_DRAW);

要注意这里新添加的内容。新创建一个数组indexData, 保存的是组成每个三角形的顶点的索引。比如第一个三角形由顶点0,1,2组成,第二个三角形由

顶点2,3,1组成,注意顶点的指定顺序要按照逆时针次序。定义了一个变量m_indexNumber,用来保存绘制图形一共需要使用的元素的数目。

然后在图像内存中生产一个缓冲区,绑定这个缓冲区。这里用的是GL_ELEMENT_ARRAY_BUFFER,表示之后用glDrawELements绘制图元的时候,会到这个缓冲区来

获得顶点的索引值。

  1. //initiate the drawing process, we want a triangle, start at index 0 and draw 3 vertices
  2. glDrawArrays(GL_TRIANGLES, 0, 3);
  3. //initiate the drawing process
  4. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
  5. glDrawElements(GL_TRIANGLES, m_indexNumber, GL_UNSIGNED_BYTE, 0);

在draw()方法中,我们不再使用前一课用的glDrawArray()方法,而是调用glDrawElement()方法,从索引数据来绘制图元。

函数需要四个参数:第一个参数是要绘制的图元,我们这里画的是三角形,选择GL_TRIANGLES。第二个参数是要绘制的元素的数目,即是索引数组的元素数目,

这里我们用m_indexNumber。第三个参数是索引数组中元素的类型。最后一个参数是指向索引数组的指针。因为我们之前已经把索引数组传送到OpenGL的

GL_ELEMENT_ARRAY_BUFFER缓冲区里去了,所以这里我们直接用0。

编译运行程序,长方形就显示出来了。

旋转

下面,我们要让这个长方形沿X轴正方向移动0.5,然后沿Y轴旋转。

首先,看shader.vert文件:

  1. // modelview
  2. uniform mat4 modelview;
  3. //the shader entry point is the main method
  4. void main()
  5. {
  6. colorVarying = color; //save the color for the fragment shader
  7. gl_Position = modelview * position; //copy the position
  8. }

我们增加了一个变量modelview,是一个4*4的矩阵。限定符uniform表示这个变量是从应用程序传递给着色器的,并且在绘制图元时保持为常量。

现在gl_Position的值是变换矩阵modelview乘给定的顶点位置。

注:关于这部分使用到的向量和矩阵库,来源于raywenderrlich写的OpenGL ES2.0 iphone开发指引,最初来源于Cocos3d框架。( http://www.raywenderlich.com/3664/opengl-es-2-0-for-iphone-tutorial)

在Lesson03.h中,增加一个变量m_modelview,保存着色器程序中uniform变量modelview的位置。

  1. //modelview uniform in the shader
  2. int m_modelview;
  1. Lesson03.mm:
  2. //get the p_w_upload points for modelview
  3. m_modelview = glGetUniformLocation(m_shader->getProgram(), "modelview");
  4. //check
  5. if (m_modelview < 0) {
  6. NSLog(@"Could not query uniform location");
  7. }

调用glGetUniformLoaction函数,将着色器程序和变量的名字传给函数,函数会返回该变量的位置。这个值我们保存起来,之后要用到。

再来看draw()函数,增加了如下代码:

  1. //modelview
  2. CC3GLMatrix *mvMatrix = [CC3GLMatrix matrix];
  3. [mvMatrix populateFromTranslation:CC3VectorMake(0.2, 0 , 0)];
  4. m_currentRotation += 1.0;
  5. [mvMatrix rotateBy:CC3VectorMake(0, m_currentRotation, 0)];
  6. glUniformMatrix4fv(m_modelview, 1, 0, mvMatrix.glMatrix);

首先,创建一个CC3GLMatrix的实例对象。关于CC3GLMatrix类,我也不是太熟悉,现在我们只要知道它有一个property成员 glMatrix,glMatrix表示的是一个4*4的浮点数矩阵数组。

然后,populateFromTranslation函数给glMatrix矩阵提供位置移动的数据,参数为指定的向量vector(x, y, z),表示在x, y, z轴上移动的距离。这样得到的矩阵glMatrix就可以通过矩阵乘法移动指定顶点的位置了。在这里,表示向x轴正方向移动0.5,其他两个方向不动。

rotateBy函数提供在x, y, z轴上的旋转数据。我们设定的值是,只沿y轴旋转,旋转角度为m_currentRotation,每次调用draw()函数,旋转角度增加1度。

最后glUniformMatrix4fv函数用我们得到的变换矩阵来更新着色器程序里的uniform变量矩阵modelview。第一个参数是要修改的uniform变量的索引位置,第二个参数是要修改的矩阵数据,这里是1个。第三个参数是第四个参数是按行主序还是列主序指定的,这里我们用GL_FALSE(0),表明是列主序指定的。最后一个参数是我们前面设定的变换矩阵。

现在,编译并运行程序,我们就可以在屏幕上看到程序运行的结果了。长方形沿x轴正方向移动了0.2,并且沿Y轴旋转。附件是教程的工程文件。

还有一个问题,旋转角度在180-360度之间时,看不到我们的长方形了。那是因为在那个范围里时,按照我们顶点的指定顺序,这两个三角形的顶点都是按顺时针方向指定的,OpenGL认为这个面是背向我们的,就没有让它显示了。下一课,我们把它改造成3D的。

转载于:https://blog.51cto.com/jimmyzhouj/884763

iOS OpenGL ES2.0教程   Lesson03 旋转相关推荐

  1. OpenGL ES2.0 – Iphone开发指引

    原文链接地址:http://www.raywenderlich.com/3664/opengl-es-2-0-for-iphone-tutorial 免责申明(必读!):本博客提供的所有教程的翻译原稿 ...

  2. OpenGL ES的性能范围(OpenGL ES2.0官方文档)

    http://blog.csdn.net/mengtnt/article/details/7773304 OpenGL ES 1.1和OpengGL ES2.0的规范中,都定义了每种实现必须支持的最低 ...

  3. Eclipse中通过Android模拟器调用OpenGL ES2.0函数操作步骤

    1.  先按照http://blog.csdn.net/fengbingchun/article/details/10439281中操作搭建好基本的Android开发环境: 2.  打开Eclipse ...

  4. 初识 OpenGL ES2.0

    原文链接:Android OpenGLES2.0(一)--了解OpenGLES2.0 OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API ...

  5. opengl es2.0 渲染文字

    在OpenGL 家族中是没有提供直接渲染文字的接口,所以我们要在opengl中显示文字,就需要借助于其他的三方库或者自己解析绘制文字,然后使用opengl中的绘制接口去渲染出文字 这里我使用的free ...

  6. opengl es2.0 使用字符偏移图渲染文字

    在OpenGL 家族中是没有提供直接渲染文字的接口,所以我们要在opengl中显示文字,就需要借助于其他的三方库或者自己解析绘制文字,然后使用opengl中的绘制接口去渲染出文字 这里我使用的free ...

  7. (转载)Cocos2dx-OpenGL ES2.0教程:初识MVP(3)

    在上一篇文章中,我在介绍vertex shader的时候挖了一个坑:CC_MVPMatrix.它其实是一个uniform,每一个cocos2d-x预定义的shader都包含有这个uniform, 但是 ...

  8. Android 基于OpenGL ES2.0 的CircleProgressBar

    之前想在播放器上加一个那种卡顿的转转提示: 类似: https://github.com/lsjwzh/MaterialLoadingProgressBar 这种效果的 由于当时没想到怎么在openg ...

  9. android双指滑动方向,OpenGL ES2.0实现手指滑动平移、双指缩放Android

    主要是实现了手指在屏幕上滑动实现平移,两个手指进行缩放.主要是这部分矩阵还挺麻烦的. 效果图如下所示: 核心部分代码如下 触控事件处理: @SuppressLint("ClickableVi ...

最新文章

  1. JavaScript初学者编程题(11)
  2. AngularJS内置指令
  3. 状态压缩 DP AHU420
  4. python简单图画程序_用Python的Turtple画图形
  5. python函数参数类型及其顺序
  6. linux命令-locale字符显示
  7. python怎么读取csv文件-Python读取csv文件(详解版,看了无师自通)
  8. SDWebImage获取到UIImage分辨率跟原图不一样
  9. App专项测试测试有哪些?
  10. 读书笔记之语法语料库和语义知识库
  11. selenium之键盘操作
  12. 2020家用千兆路由器哪款好_2020家用路由器推荐
  13. Docker容器设置自动启动的方法
  14. 关键对话(如何高效沟通)读书总结
  15. ui设计需要学编程吗难不难学习
  16. 电脑死机的原因和防止方法
  17. Josh 的学习笔记之数字通信(Part 1——信号和频谱)
  18. 常见安防存储估算标准
  19. 清华脑机接口需要学计算机专业的吗,清华大学
  20. 个人计算机是由单片,《计算机应础》期终考试卷(B卷).doc

热门文章

  1. 基于组织目标采用合适的敏捷方法
  2. linux cut 命令详解
  3. Hyper-V 3.0服务器虚拟化:打造坚固的云
  4. NPOI导出Excel表功能实现(多个工作簿)
  5. Q95:纹理映射(Texture Mapping)(3)——Triangle Meshes
  6. 机器学习算法(一): 基于逻辑回归的分类预测-Task01
  7. 如何商业智能平台BI的成本
  8. 大数据分析平台应注意哪些方面
  9. 大数据是如何作用于实体经济
  10. 2×3卡方检验prism_卡方检验(最强总结)