1. OpenGL ES实现

1.1 颜色填充

4、OpenGL ES 颜色纹理混合金字塔 - 图1

1.1.1 着色器

  • 顶点着色器
  1. attribute vec4 position;
  2. attribute vec4 positionColor;
  3. uniform mat4 projectionMatrix;
  4. uniform mat4 modelViewMatrix;
  5. varying lowp vec4 varyColor;
  6. void main() {
  7. varyColor = positionColor;
  8. vec4 vPos = projectionMatrix * modelViewMatrix * position;
  9. gl_Position = vPos;
  10. }
  • 片元着色器
  1. varying lowp vec4 varyColor;
  2. void main() {
  3. gl_FragColor = varyColor;
  4. }

1.1.2 绘制过程

  1. - (void)drawPyramid
  2. {
  3. //1.设置图层
  4. [self setupLayer];
  5. //2.设置上下文
  6. [self setupContext];
  7. //3.清空缓存区
  8. [self deletBuffer];
  9. //4.设置renderBuffer
  10. [self setupRenderBuffer];
  11. //5.设置frameBuffer
  12. [self setupFrameBuffer];
  13. //6.绘制
  14. [self render];
  15. }
  • 设置图层
  1. - (void)setupLayer {
  2. self.myEagLayer = (CAEAGLLayer *)self.layer;
  3. [self setContentScaleFactor:[[UIScreen mainScreen]scale]];
  4. self.myEagLayer.opaque = YES;
  5. self.myEagLayer.drawableProperties = @{
  6. kEAGLDrawablePropertyRetainedBacking : @NO,
  7. kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8
  8. };
  9. }
  • 设置上下文
  1. - (void)setupContext {
  2. EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
  3. EAGLContext *context = [[EAGLContext alloc]initWithAPI:api];
  4. if (!context) {
  5. NSLog(@"Create Context Failed");
  6. return;
  7. }
  8. if (![EAGLContext setCurrentContext:context]) {
  9. NSLog(@"Set Current Context Failed");
  10. return;
  11. }
  12. self.myContext = context;
  13. }
  • 清空缓存区
  1. - (void)deletBuffer {
  2. glDeleteBuffers(1, &_myColorRenderBuffer);
  3. _myColorRenderBuffer = 0;
  4. glDeleteBuffers(1, &_myColorFrameBuffer);
  5. _myColorFrameBuffer = 0;
  6. }
  • 设置renderBuffer
  1. - (void)setupRenderBuffer {
  2. //1.定义一个缓存区
  3. GLuint buffer;
  4. //2.申请一个缓存区标志
  5. glGenRenderbuffers(1, &buffer);
  6. //3.
  7. self.myColorRenderBuffer = buffer;
  8. //4.将标识符绑定到GL_RENDERBUFFER
  9. glBindRenderbuffer(GL_RENDERBUFFER, self.myColorRenderBuffer);
  10. [self.myContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.myEagLayer];
  11. }
  • 设置frameBuffer
  1. - (void)setupFrameBuffer {
  2. //1.定义一个缓存区
  3. GLuint buffer;
  4. //2.申请一个缓存区标志
  5. glGenFramebuffers(1, &buffer);
  6. //3.
  7. self.myColorFrameBuffer = buffer;
  8. //4.设置当前的framebuffer
  9. glBindFramebuffer(GL_FRAMEBUFFER, self.myColorFrameBuffer);
  10. //5.将_myColorRenderBuffer 装配到GL_COLOR_ATTACHMENT0 附着点上
  11. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.myColorRenderBuffer);
  12. }
  • 绘制
  1. - (void)render {
  2. //1.清屏颜色
  3. glClearColor(0, 0.0, 0, 1.0);
  4. glClear(GL_COLOR_BUFFER_BIT);
  5. CGFloat scale = [[UIScreen mainScreen] scale];
  6. //2.设置视口
  7. glViewport(self.frame.origin.x * scale, self.frame.origin.y * scale, self.frame.size.width * scale, self.frame.size.height * scale);
  8. //3.获取顶点着色程序、片元着色器程序文件位置
  9. NSString* vertFile = [[NSBundle mainBundle] pathForResource:@"shaderv" ofType:@"glsl"];
  10. NSString* fragFile = [[NSBundle mainBundle] pathForResource:@"shaderf" ofType:@"glsl"];
  11. //4.判断self.myProgram是否存在,存在则清空其文件
  12. if (self.myProgram) {
  13. glDeleteProgram(self.myProgram);
  14. self.myProgram = 0;
  15. }
  16. //5.加载程序到myProgram中来。
  17. self.myProgram = [self loadShader:vertFile frag:fragFile];
  18. //6.链接
  19. glLinkProgram(self.myProgram);
  20. GLint linkSuccess;
  21. //7.获取链接状态
  22. glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkSuccess);
  23. if (linkSuccess == GL_FALSE) {
  24. GLchar messages[256];
  25. glGetProgramInfoLog(self.myProgram, sizeof(messages), 0, &messages[0]);
  26. NSString *messageString = [NSString stringWithUTF8String:messages];
  27. NSLog(@"error%@", messageString);
  28. return ;
  29. }else {
  30. glUseProgram(self.myProgram);
  31. }
  32. //8.创建顶点数组 & 索引数组
  33. //(1)顶点数组 前3顶点值(x,y,z),后3位颜色值(RGB)
  34. GLfloat attrArr[] = {
  35. -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, //左上0
  36. 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, //右上1
  37. -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, //左下2
  38. 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, //右下3
  39. 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //顶点4
  40. };
  41. //(2).索引数组
  42. GLuint indices[] = {
  43. 0, 3, 2,
  44. 0, 1, 3,
  45. 0, 2, 4,
  46. 0, 4, 1,
  47. 2, 3, 4,
  48. 1, 4, 3,
  49. };
  50. //(3).判断顶点缓存区是否为空,如果为空则申请一个缓存区标识符
  51. if (self.myVertices == 0) {
  52. glGenBuffers(1, &_myVertices);
  53. }
  54. //9.-----处理顶点数据-------
  55. //(1).将_myVertices绑定到GL_ARRAY_BUFFER标识符上
  56. glBindBuffer(GL_ARRAY_BUFFER, _myVertices);
  57. //(2).把顶点数据从CPU内存复制到GPU上
  58. glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW);
  59. //(3).将顶点数据通过myPrograme中的传递到顶点着色程序的position
  60. //1.glGetAttribLocation,用来获取vertex attribute的入口的.
  61. //2.告诉OpenGL ES,通过glEnableVertexAttribArray,
  62. //3.最后数据是通过glVertexAttribPointer传递过去的。
  63. //注意:第二参数字符串必须和shaderv.vsh中的输入变量:position保持一致
  64. GLuint position = glGetAttribLocation(self.myProgram, "position");
  65. //(4).打开position
  66. glEnableVertexAttribArray(position);
  67. //(5).设置读取方式
  68. //参数1:index,顶点数据的索引
  69. //参数2:size,每个顶点属性的组件数量,1,2,3,或者4.默认初始值是4.
  70. //参数3:type,数据中的每个组件的类型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默认初始值为GL_FLOAT
  71. //参数4:normalized,固定点数据值是否应该归一化,或者直接转换为固定值。(GL_FALSE)
  72. //参数5:stride,连续顶点属性之间的偏移量,默认为0;
  73. //参数6:指定一个指针,指向数组中的第一个顶点属性的第一个组件。默认为0
  74. glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, NULL);
  75. //10.--------处理顶点颜色值-------
  76. //(1).glGetAttribLocation,用来获取vertex attribute的入口的.
  77. //注意:第二参数字符串必须和shaderv.glsl中的输入变量:positionColor保持一致
  78. GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");
  79. //(2).设置合适的格式从buffer里面读取数据
  80. glEnableVertexAttribArray(positionColor);
  81. //(3).设置读取方式
  82. //参数1:index,顶点数据的索引
  83. //参数2:size,每个顶点属性的组件数量,1,2,3,或者4.默认初始值是4.
  84. //参数3:type,数据中的每个组件的类型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默认初始值为GL_FLOAT
  85. //参数4:normalized,固定点数据值是否应该归一化,或者直接转换为固定值。(GL_FALSE)
  86. //参数5:stride,连续顶点属性之间的偏移量,默认为0;
  87. //参数6:指定一个指针,指向数组中的第一个顶点属性的第一个组件。默认为0
  88. glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (float *)NULL + 3);
  89. //11.找到myProgram中的projectionMatrix、modelViewMatrix 2个矩阵的地址。如果找到则返回地址,否则返回-1,表示没有找到2个对象。
  90. GLuint projectionMatrixSlot = glGetUniformLocation(self.myProgram, "projectionMatrix");
  91. GLuint modelViewMatrixSlot = glGetUniformLocation(self.myProgram, "modelViewMatrix");
  92. float width = self.frame.size.width;
  93. float height = self.frame.size.height;
  94. //12.创建4 * 4投影矩阵
  95. KSMatrix4 _projectionMatrix;
  96. //(1)获取单元矩阵
  97. ksMatrixLoadIdentity(&_projectionMatrix);
  98. //(2)计算纵横比例 = 长/宽
  99. float aspect = width / height; //长宽比
  100. //(3)获取透视矩阵
  101. /*
  102. 参数1:矩阵
  103. 参数2:视角,度数为单位
  104. 参数3:纵横比
  105. 参数4:近平面距离
  106. 参数5:远平面距离
  107. 参考PPT
  108. */
  109. ksPerspective(&_projectionMatrix, 30.0, aspect, 5.0f, 20.0f); //透视变换,视角30°
  110. //(4)将投影矩阵传递到顶点着色器
  111. /*
  112. void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  113. 参数列表:
  114. location:指要更改的uniform变量的位置
  115. count:更改矩阵的个数
  116. transpose:是否要转置矩阵,并将它作为uniform变量的值。必须为GL_FALSE
  117. value:执行count个元素的指针,用来更新指定uniform变量
  118. */
  119. glUniformMatrix4fv(projectionMatrixSlot, 1, GL_FALSE, (GLfloat*)&_projectionMatrix.m[0][0]);
  120. //13.创建一个4 * 4 矩阵,模型视图矩阵
  121. KSMatrix4 _modelViewMatrix;
  122. //(1)获取单元矩阵
  123. ksMatrixLoadIdentity(&_modelViewMatrix);
  124. //(2)平移,z轴平移-10
  125. ksTranslate(&_modelViewMatrix, 0.0, 0.0, -10.0);
  126. //(3)创建一个4 * 4 矩阵,旋转矩阵
  127. KSMatrix4 _rotationMatrix;
  128. //(4)初始化为单元矩阵
  129. ksMatrixLoadIdentity(&_rotationMatrix);
  130. //(5)旋转
  131. ksRotate(&_rotationMatrix, xDegree, 1.0, 0.0, 0.0); //绕X轴
  132. ksRotate(&_rotationMatrix, yDegree, 0.0, 1.0, 0.0); //绕Y轴
  133. ksRotate(&_rotationMatrix, zDegree, 0.0, 0.0, 1.0); //绕Z轴
  134. //(6)把变换矩阵相乘.将_modelViewMatrix矩阵与_rotationMatrix矩阵相乘,结合到模型视图
  135. ksMatrixMultiply(&_modelViewMatrix, &_rotationMatrix, &_modelViewMatrix);
  136. //(7)将模型视图矩阵传递到顶点着色器
  137. /*
  138. void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  139. 参数列表:
  140. location:指要更改的uniform变量的位置
  141. count:更改矩阵的个数
  142. transpose:是否要转置矩阵,并将它作为uniform变量的值。必须为GL_FALSE
  143. value:执行count个元素的指针,用来更新指定uniform变量
  144. */
  145. glUniformMatrix4fv(modelViewMatrixSlot, 1, GL_FALSE, (GLfloat*)&_modelViewMatrix.m[0][0]);
  146. //14.开启剔除操作效果
  147. glEnable(GL_CULL_FACE);
  148. //15.使用索引绘图
  149. /*
  150. void glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices);
  151. 参数列表:
  152. mode:要呈现的画图的模型
  153. GL_POINTS
  154. GL_LINES
  155. GL_LINE_LOOP
  156. GL_LINE_STRIP
  157. GL_TRIANGLES
  158. GL_TRIANGLE_STRIP
  159. GL_TRIANGLE_FAN
  160. count:绘图个数
  161. type:类型
  162. GL_BYTE
  163. GL_UNSIGNED_BYTE
  164. GL_SHORT
  165. GL_UNSIGNED_SHORT
  166. GL_INT
  167. GL_UNSIGNED_INT
  168. indices:绘制索引数组
  169. */
  170. glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, indices);
  171. //16.要求本地窗口系统显示OpenGL ES渲染<目标>
  172. [self.myContext presentRenderbuffer:GL_RENDERBUFFER];
  173. }
  174. #pragma mark -- Shader
  175. -(GLuint)loadShader:(NSString *)vert frag:(NSString *)frag {
  176. //创建2个临时的变量,verShader,fragShader
  177. GLuint verShader,fragShader;
  178. //创建一个Program
  179. GLuint program = glCreateProgram();
  180. //编译文件
  181. //编译顶点着色程序、片元着色器程序
  182. //参数1:编译完存储的底层地址
  183. //参数2:编译的类型,GL_VERTEX_SHADER(顶点)、GL_FRAGMENT_SHADER(片元)
  184. //参数3:文件路径
  185. [self compileShader:&verShader type:GL_VERTEX_SHADER file:vert];
  186. [self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:frag];
  187. //创建最终的程序
  188. glAttachShader(program, verShader);
  189. glAttachShader(program, fragShader);
  190. //释放不需要的shader
  191. glDeleteShader(verShader);
  192. glDeleteShader(fragShader);
  193. return program;
  194. }
  195. //链接shader
  196. - (void)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file {
  197. //读取文件路径字符串
  198. NSString *content = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];
  199. //获取文件路径字符串,C语言字符串
  200. const GLchar *source = (GLchar *)[content UTF8String];
  201. //创建一个shader(根据type类型)
  202. *shader = glCreateShader(type);
  203. //将顶点着色器源码附加到着色器对象上。
  204. //参数1:shader,要编译的着色器对象 *shader
  205. //参数2:numOfStrings,传递的源码字符串数量 1个
  206. //参数3:strings,着色器程序的源码(真正的着色器程序源码)
  207. //参数4:lenOfStrings,长度,具有每个字符串长度的数组,或NULL,这意味着字符串是NULL终止的
  208. glShaderSource(*shader, 1, &source, NULL);
  209. //把着色器源代码编译成目标代码
  210. glCompileShader(*shader);
  211. }
  212. #pragma mark - XYClick
  213. - (IBAction)XClick:(id)sender {
  214. //开启定时器
  215. [self myTimer];
  216. //更新的是X还是Y
  217. bX = !bX;
  218. }
  219. - (IBAction)YClick:(id)sender {
  220. //开启定时器
  221. [self myTimer];
  222. //更新的是X还是Y
  223. bY = !bY;
  224. }
  225. - (IBAction)ZClick:(id)sender {
  226. //开启定时器
  227. [self myTimer];
  228. //更新的是X还是Y
  229. bZ = !bZ;
  230. }
  231. - (NSTimer *)myTimer {
  232. if (!_myTimer) {
  233. _myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(reDegree) userInfo:nil repeats:YES];
  234. }
  235. return _myTimer;
  236. }
  237. - (void)reDegree {
  238. //如果停止X轴旋转,X = 0则度数就停留在暂停前的度数.
  239. //更新度数
  240. xDegree += bX * 5;
  241. yDegree += bY * 5;
  242. zDegree += bZ * 5;
  243. //重新渲染
  244. [self render];
  245. }

1.2 纹理填充

4、OpenGL ES 颜色纹理混合金字塔 - 图2

1.2.1 着色器

  • 顶点着色器
  1. attribute vec4 position;
  2. attribute vec2 textCoordinate;
  3. uniform mat4 projectionMatrix;
  4. uniform mat4 modelViewMatrix;
  5. varying lowp vec2 varyTextCoord;
  6. void main() {
  7. varyTextCoord = textCoordinate;
  8. vec4 vPos = projectionMatrix * modelViewMatrix * position;
  9. gl_Position = vPos;
  10. }
  • 片元着色器
  1. precision highp float;
  2. varying lowp vec2 varyTextCoord;
  3. uniform sampler2D colorMap;
  4. void main() {
  5. gl_FragColor = texture2D(colorMap, varyTextCoord);
  6. }

1.2.2 绘制过程

这里写了需要修改的部分。

  1. GLfloat attrArr[] = {
  2. -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,//左上
  3. 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,//右上
  4. -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,//左下
  5. 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,//右下
  6. 0.0f, 0.0f, 1.0f, 0.5f, 0.5f,//顶点
  7. };
  8. // 设置顶点坐标
  9. GLuint position = glGetAttribLocation(self.myProgram, "position");
  10. glEnableVertexAttribArray(position);
  11. glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, NULL);
  12. // 设置纹理坐标
  13. GLuint textCoordinate = glGetAttribLocation(self.myProgram, "textCoordinate");
  14. glEnableVertexAttribArray(textCoordinate);
  15. glVertexAttribPointer(textCoordinate, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (float *)NULL + 3);
  16. // 设置纹理
  17. [self setupTexture:@"qiyu"];
  18. glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), 0);
  • 加载纹理
  1. //从图片中加载纹理
  2. - (GLuint)setupTexture:(NSString *)fileName {
  3. //1、将 UIImage 转换为 CGImageRef
  4. CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
  5. //判断图片是否获取成功
  6. if (!spriteImage) {
  7. NSLog(@"Failed to load image %@", fileName);
  8. exit(1);
  9. }
  10. //2、读取图片的大小,宽和高
  11. size_t width = CGImageGetWidth(spriteImage);
  12. size_t height = CGImageGetHeight(spriteImage);
  13. //3.获取图片字节数 宽*高*4(RGBA)
  14. GLubyte * spriteData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
  15. //4.创建上下文
  16. /*
  17. 参数1:data,指向要渲染的绘制图像的内存地址
  18. 参数2:width,bitmap的宽度,单位为像素
  19. 参数3:height,bitmap的高度,单位为像素
  20. 参数4:bitPerComponent,内存中像素的每个组件的位数,比如32位RGBA,就设置为8
  21. 参数5:bytesPerRow,bitmap的没一行的内存所占的比特数
  22. 参数6:colorSpace,bitmap上使用的颜色空间 kCGImageAlphaPremultipliedLast:RGBA
  23. */
  24. CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4,CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
  25. //5、在CGContextRef上--> 将图片绘制出来
  26. /*
  27. CGContextDrawImage 使用的是Core Graphics框架,坐标系与UIKit 不一样。UIKit框架的原点在屏幕的左上角,Core Graphics框架的原点在屏幕的左下角。
  28. CGContextDrawImage
  29. 参数1:绘图上下文
  30. 参数2:rect坐标
  31. 参数3:绘制的图片
  32. */
  33. CGRect rect = CGRectMake(0, 0, width, height);
  34. //6.使用默认方式绘制
  35. CGContextDrawImage(spriteContext, rect, spriteImage);
  36. //7、画图完毕就释放上下文
  37. CGContextRelease(spriteContext);
  38. //8、绑定纹理到默认的纹理ID(
  39. glBindTexture(GL_TEXTURE_2D, 0);
  40. //9.设置纹理属性
  41. /*
  42. 参数1:纹理维度
  43. 参数2:线性过滤、为s,t坐标设置模式
  44. 参数3:wrapMode,环绕模式
  45. */
  46. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  47. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  48. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  49. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  50. float fw = width, fh = height;
  51. //10.载入纹理2D数据
  52. /*
  53. 参数1:纹理模式,GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
  54. 参数2:加载的层次,一般设置为0
  55. 参数3:纹理的颜色值GL_RGBA
  56. 参数4:宽
  57. 参数5:高
  58. 参数6:border,边界宽度
  59. 参数7:format
  60. 参数8:type
  61. 参数9:纹理数据
  62. */
  63. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
  64. //11.释放spriteData
  65. free(spriteData);
  66. return 0;
  67. }

1.3 纹理颜色混合

颜色混合逻辑主要在片元着色器中。
4、OpenGL ES 颜色纹理混合金字塔 - 图3

1.3.1 着色器

  • 顶点着色器
  1. attribute vec4 position;
  2. attribute vec4 positionColor;
  3. attribute vec2 textCoordinate;
  4. uniform mat4 projectionMatrix;
  5. uniform mat4 modelViewMatrix;
  6. varying lowp vec4 varyColor;
  7. varying lowp vec2 varyTextCoord;
  8. void main() {
  9. varyTextCoord = textCoordinate;
  10. varyColor = positionColor;
  11. vec4 vPos = projectionMatrix * modelViewMatrix * position;
  12. gl_Position = vPos;
  13. }
  • 片元着色器 (核心逻辑)
  1. precision highp float;
  2. varying lowp vec4 varyColor;
  3. varying lowp vec2 varyTextCoord;
  4. uniform sampler2D colorMap;
  5. void main() {
  6. vec4 textureColor = texture2D(colorMap, varyTextCoord);
  7. float alpha = 0.3;
  8. gl_FragColor = varyColor * (1.0 - alpha) + textureColor * alpha;
  9. }

1.3.2 绘制过程

这里写了需要修改的部分。

  1. GLfloat attrArr[] = {
  2. -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,//左上
  3. 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,//右上
  4. -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,//左下
  5. 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,//右下
  6. 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f,//顶点
  7. };
  8. // 设置顶点数据
  9. glEnableVertexAttribArray(GLKVertexAttribPosition);
  10. glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, NULL);
  11. // 设置颜色数据
  12. glEnableVertexAttribArray(GLKVertexAttribColor);
  13. glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 3);
  14. // 设置颜色数据
  15. glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
  16. glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 6);

2. GLKit实现

GLKit实现会少很多代码,这里一次性给出代码。

2.1 纹理颜色混合

4、OpenGL ES 颜色纹理混合金字塔 - 图4

  1. -(void)viewDidLoad {
  2. [super viewDidLoad];
  3. //1.新建图层
  4. [self setupContext];
  5. //2.渲染图形
  6. [self render];
  7. }
  8. //2.渲染图形
  9. -(void)render {
  10. //1.顶点数据
  11. //前3个元素,是顶点数据;中间3个元素,是顶点颜色值,最后2个是纹理坐标
  12. GLfloat attrArr[] = {
  13. -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,//左上
  14. 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,//右上
  15. -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,//左下
  16. 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,//右下
  17. 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f,//顶点
  18. };
  19. //2.绘图索引
  20. GLuint indices[] = {
  21. 0, 3, 2,
  22. 0, 1, 3,
  23. 0, 2, 4,
  24. 0, 4, 1,
  25. 2, 3, 4,
  26. 1, 4, 3,
  27. };
  28. //顶点个数
  29. self.count = sizeof(indices) /sizeof(GLuint);
  30. //将顶点数组放入数组缓冲区中 GL_ARRAY_BUFFER
  31. GLuint buffer;
  32. glGenBuffers(1, &buffer);
  33. glBindBuffer(GL_ARRAY_BUFFER, buffer);
  34. glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_STATIC_DRAW);
  35. //将索引数组存储到索引缓冲区 GL_ELEMENT_ARRAY_BUFFER
  36. GLuint index;
  37. glGenBuffers(1, &index);
  38. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
  39. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  40. //使用顶点数据
  41. glEnableVertexAttribArray(GLKVertexAttribPosition);
  42. glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, NULL);
  43. //使用颜色数据
  44. glEnableVertexAttribArray(GLKVertexAttribColor);
  45. glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 3);
  46. //使用纹理数据
  47. glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
  48. glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 6);
  49. //着色器
  50. self.mEffect = [[GLKBaseEffect alloc]init];
  51. //加载纹理
  52. NSString *filePath = [[NSBundle mainBundle]pathForResource:@"qiyu" ofType:@"jpg"];
  53. NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft : @(YES)};
  54. GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
  55. self.mEffect.texture2d0.enabled = YES;
  56. self.mEffect.texture2d0.name = textureInfo.name;
  57. self.mEffect.texture2d0.target = textureInfo.target;
  58. //投影视图
  59. CGSize size = self.view.bounds.size;
  60. float aspect = fabs(size.width / size.height);
  61. GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 100.0);
  62. projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0f, 1.0f, 1.0f);
  63. self.mEffect.transform.projectionMatrix = projectionMatrix;
  64. //模型视图
  65. GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
  66. self.mEffect.transform.modelviewMatrix = modelViewMatrix;
  67. //定时器
  68. double seconds = 0.1;
  69. timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
  70. dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC, 0.0);
  71. dispatch_source_set_event_handler(timer, ^{
  72. self.XDegree += 0.1f * self.XB;
  73. self.YDegree += 0.1f * self.YB;
  74. self.ZDegree += 0.1f * self.ZB ;
  75. });
  76. dispatch_resume(timer);
  77. }
  78. //场景数据变化
  79. - (void)update {
  80. GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.5);
  81. modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.XDegree);
  82. modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, self.YDegree);
  83. modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, self.ZDegree);
  84. self.mEffect.transform.modelviewMatrix = modelViewMatrix;
  85. }
  86. - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
  87. glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
  88. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  89. [self.mEffect prepareToDraw];
  90. glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0);
  91. }
  92. //1.新建图层
  93. - (void)setupContext
  94. {
  95. //1.新建OpenGL ES上下文
  96. self.mContext = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
  97. [EAGLContext setCurrentContext:self.mContext];
  98. glEnable(GL_DEPTH_TEST);
  99. GLKView *view = (GLKView *)self.view;
  100. view.context = self.mContext;
  101. view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
  102. view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
  103. }
  104. #pragma mark -XYZClick
  105. - (IBAction)XClick:(id)sender {
  106. _XB = !_XB;
  107. }
  108. - (IBAction)YClick:(id)sender {
  109. _YB = !_YB;
  110. }
  111. - (IBAction)ZClick:(id)sender {
  112. _ZB = !_ZB;
  113. }