OpenGL 11 - 索引繪圖 - GLSL與GLKit案例


一、索引繪圖

若要繪制下圖目標圖形,按普通處理方式則需要一個個進行N多個三角形的頂點處理。圖中所用到頂點重復性很高,其實只有7個不同的頂點 --> 索引繪圖 --> 將頂點按索引信息進行面的繪制 --> 索引數組:{1,2,3}{3,2,4}{4,2,7}{7,2,5}  {4,7,2}{2,7,6}

索引繪圖與圖元裝配中的三角形連接方式結合繪制所需圖形。

二、案例繪制一個三角錐金字塔 - GLSL

1、效果:

2、頂點數據:

上圖,三角錐金字塔所需頂點數據 和 索引信息

3、主要代碼

view 代碼:

  1 //
  2 //  MyGLSLView.m
  3 //  GL_Demo_GLSL
  4 //
  5 //  Created by Domy on 2020/7/31.
  6 //  Copyright © 2020 Domy. All rights reserved.
  7 //
  8 
  9 
 10 /*
 11  不采用 GLKBaseEffect,使用編譯鏈接自定義的着色器(shader)。用簡單的 glsl 語言來實現頂點、片元着色器,並圖形進行簡單的變換。
 12  思路:
 13  1.創建圖層
 14  2.創建上下文
 15  3.清空緩存區
 16  4.設置RenderBuffer
 17  5.設置FrameBuffer
 18  6.開始繪制
 19  */
 20 
 21 #import "MyGLSLView.h"
 22 
 23 #import <OpenGLES/ES2/gl.h>
 24 
 25 #import "GLESMath.h"
 26 
 27 
 28 @interface MyGLSLView () {
 29     
 30     float xDegree;
 31     float yDegree;
 32     float zDegree;
 33     BOOL bX;
 34     BOOL bY;
 35     BOOL bZ;
 36     NSTimer *myTimer;
 37 }
 38 
 39 @property (nonatomic, strong) CAEAGLLayer *myEGLLayer;// 圖層
 40 @property (nonatomic, strong) EAGLContext *myContext;// 上下文
 41 
 42 @property (nonatomic, assign) GLuint myColorFrameBuffer;//
 43 @property (nonatomic, assign) GLuint myColorRenderBuffer;// 渲染緩沖區
 44 
 45 @property (nonatomic, assign) GLuint myProgram;
 46 
 47 @end
 48 
 49 
 50 @implementation MyGLSLView
 51 
 52 // 重寫系統 layer 方法
 53 +(Class)layerClass {
 54     return [CAEAGLLayer class];
 55 }
 56 
 57 - (void)layoutSubviews {
 58     
 59     // 1. 創建設置圖層
 60     // 設置 layer
 61     self.myEGLLayer = (CAEAGLLayer *)self.layer;
 62     
 63     // 設置 scale
 64     [self setContentScaleFactor:[[UIScreen mainScreen] scale]];
 65     
 66     // 設置屬性
 67     /*
 68      kEAGLDrawablePropertyRetainedBacking:繪圖表面顯示后,是否保留其內容。
 69      kEAGLDrawablePropertyColorFormat:可繪制表面的內部顏色緩存區格式,這個key對應的值是一個NSString指定特定顏色緩存區對象。默認是kEAGLColorFormatRGBA8;
 70      
 71      kEAGLColorFormatRGBA8:32位RGBA的顏色,4*8=32位
 72      kEAGLColorFormatRGB565:16位RGB的顏色,
 73      kEAGLColorFormatSRGBA8:sRGB代表了標准的紅、綠、藍,即CRT顯示器、LCD顯示器、投影機、打印機以及其他設備中色彩再現所使用的三個基本色素,sRGB的色彩空間基於獨立的色彩坐標,可以使色彩在不同的設備使用傳輸中對應於同一個色彩坐標體系,而不受這些設備各自具有的不同色彩坐標的影響。
 74      */
 75 //    self.myEGLLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking:@(NO),kEAGLDrawablePropertyColorFormat:kEAGLColorFormatRGBA8};
 76     self.myEGLLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:@false,kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8,kEAGLDrawablePropertyColorFormat,nil];
 77 
 78     
 79     // 2. 設置上下文
 80     self.myContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
 81     if (!self.myContext) {
 82         NSLog(@"create context failed!");
 83         return;
 84     }
 85     BOOL isSetSuccess = [EAGLContext setCurrentContext:self.myContext];
 86     if (!isSetSuccess) {
 87         return;
 88     }
 89     
 90     
 91     // 3. 清空緩沖區
 92     glDeleteBuffers(1, &_myColorRenderBuffer);
 93     self.myColorRenderBuffer = 0;
 94     glDeleteBuffers(1, &_myColorFrameBuffer);
 95     self.myColorFrameBuffer = 0;
 96     
 97     
 98     // 4. 設置渲染緩沖區 renderBuffer
 99     // 生成緩沖區 ID
100     GLuint rb;
101     glGenRenderbuffers(1, &rb);
102     self.myColorRenderBuffer = rb;
103     // 綁定緩沖區
104     glBindRenderbuffer(GL_RENDERBUFFER, self.myColorRenderBuffer);
105     
106     // 綁到 context: contect 與 eagllayer綁定在一起
107     [self.myContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.myEGLLayer];
108     
109     
110     // 5. 設置幀緩沖區 FrameBuffer
111     glGenBuffers(1, &_myColorFrameBuffer);
112     glBindFramebuffer(GL_FRAMEBUFFER, self.myColorFrameBuffer);
113     
114     // 渲染緩沖區 與 幀緩沖區綁在一起
115     /*
116      target:
117      attachment:將 renderBuffer 附着到frameBuffer的哪個附着點上
118      renderbuffertarget
119      renderbuffer
120      */
121     //    glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
122     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.myColorRenderBuffer);
123     
124     
125     // 開始繪制
126     [self renderLayer];
127     
128 }
129 
130 - (void)renderLayer {
131     
132     glClearColor(0.7, 0.7, 0.7, 1);
133     glClear(GL_COLOR_BUFFER_BIT);
134     
135     /// 1. 設置視口
136     CGFloat mainScale = [UIScreen mainScreen].scale;
137     glViewport(self.frame.origin.x * mainScale, self.frame.origin.y * mainScale, self.frame.size.width * mainScale, self.frame.size.height * mainScale);
138     
139     /// 2. 讀取着色器代碼
140     // 定義路徑
141     NSString *verPath = [[NSBundle mainBundle] pathForResource:@"shaderv" ofType:@"vsh"];
142     NSString *fragPath = [[NSBundle mainBundle] pathForResource:@"shaderf" ofType:@"fsh"];
143     
144     /// 3. 加載着色器
145     if (self.myProgram) {
146         // delete
147         glDeleteProgram(self.myProgram);
148         self.myProgram = 0;
149     }
150     self.myProgram = [self loadShadersWithVertex:verPath Withfrag:fragPath];
151     
152     /// 4. 鏈接 program
153     glLinkProgram(self.myProgram);
154     // 獲取連接狀態
155     GLint linkStatus;
156     glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkStatus);
157     if (linkStatus == GL_FALSE) {// 鏈接出錯
158         // 獲取錯誤信息 log
159         GLchar message[512];
160         glGetProgramInfoLog(self.myProgram, sizeof(message), 0, &message[0]);
161         NSString *messageString = [NSString stringWithUTF8String:message];
162         NSLog(@"Program Link Error:%@",messageString);
163         return;
164     }
165     
166     /// 5. 使用 program
167     glUseProgram(self.myProgram);
168     
169     
170     
171     /// 6. 設置頂點、顏色RGB
172     GLfloat attrArr[] = {
173         
174         -0.5f, 0.5f, 0.0f,      1.0f, 0.0f, 1.0f, //左上0
175         0.5f, 0.5f, 0.0f,       1.0f, 0.0f, 1.0f, //右上1
176         -0.5f, -0.5f, 0.0f,     1.0f, 1.0f, 1.0f, //左下2
177         
178         0.5f, -0.5f, 0.0f,      1.0f, 1.0f, 1.0f, //右下3
179         0.0f, 0.0f, 1.0f,       0.0f, 1.0f, 0.0f, //頂點4
180     };
181     // 索引數組
182     GLuint indices[] = {
183         0, 3, 2,
184         0, 1, 3,
185         0, 2, 4,
186         0, 4, 1,
187         2, 3, 4,
188         1, 4, 3,
189     };
190     
191     /// 7. copy 到頂點緩沖區
192     GLuint buffer;
193     glGenBuffers(1, &buffer);
194     glBindBuffer(GL_ARRAY_BUFFER, buffer);
195     // 頂點數據 copy 到緩沖區
196     glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW);
197 
198     /// 8. 打開通道
199     // 8.1 頂點
200     // 獲取通道 ID
201     /*
202      glGetAttribLocation(GLuint program, const GLchar *name)
203      program:
204      name: 給誰傳 --> .vsh 的 position
205      */
206     GLuint position = glGetAttribLocation(self.myProgram, "position");
207     // 打開通道
208     glEnableVertexAttribArray(position);
209     // 讀數據
210     glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, NULL);
211 
212     // 頂點顏色
213      GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");
214      // 設置合適的方式從 buffer 里面讀取數據
215      glEnableVertexAttribArray(positionColor);
216      glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (float *)NULL + 3);
217     
218     // 矩陣變換
219     [self configMartix];
220     
221     
222     /// 11.  繪制
223 //    glDrawArrays(GL_TRIANGLES, 0, 6);
224     
225     glEnable(GL_CULL_FACE);
226     glEnable(GL_DEPTH_TEST);
227 
228     
229     // 使用索引繪圖
230     /*
231      void glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices);
232      參數列表:
233      mode:要呈現的畫圖的模型
234                 GL_POINTS
235                 GL_LINES
236                 GL_LINE_LOOP
237                 GL_LINE_STRIP
238                 GL_TRIANGLES
239                 GL_TRIANGLE_STRIP
240                 GL_TRIANGLE_FAN
241      count:繪圖個數
242      type:類型
243              GL_BYTE
244              GL_UNSIGNED_BYTE
245              GL_SHORT
246              GL_UNSIGNED_SHORT
247              GL_INT
248              GL_UNSIGNED_INT
249      indices:繪制索引數組
250 
251      */
252     glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, indices);
253     
254     
255     
256     // 12. 從渲染緩沖區顯示到屏幕
257     [self.myContext presentRenderbuffer:GL_RENDERBUFFER];
258 }
259 
260 // 旋轉 - 矩陣變換
261 - (void)configMartix {
262     
263     // 1.找到myProgram中的projectionMatrix、modelViewMatrix 2個矩陣的地址。如果找到則返回地址,否則返回-1,表示沒有找到2個對象。
264     GLuint projectionMatrixSlot = glGetUniformLocation(self.myProgram, "projectionMatrix");
265     GLuint modelViewMatrixSlot = glGetUniformLocation(self.myProgram, "modelViewMatrix");
266     
267     float width = self.frame.size.width;
268     float height = self.frame.size.height;
269     
270     // 2.創建4 * 4投影矩陣
271     KSMatrix4 _projectionMatrix;
272     //(1)獲取單元矩陣
273     ksMatrixLoadIdentity(&_projectionMatrix);
274     //(2)計算縱橫比例 = 長/寬
275     float aspect = width / height; //長寬比
276     //(3)獲取透視矩陣
277     /*
278      參數1:矩陣
279      參數2:視角,度數為單位
280      參數3:縱橫比
281      參數4:近平面距離
282      參數5:遠平面距離
283 284      */
285     ksPerspective(&_projectionMatrix, 30.0, aspect, 5.0f, 20.0f); //透視變換,視角30°
286     //(4)將投影矩陣傳遞到頂點着色器
287     /*
288      void glUniformMatrix4fv(GLint location,  GLsizei count,  GLboolean transpose,  const GLfloat *value);
289      參數列表:
290      location:指要更改的uniform變量的位置
291      count:更改矩陣的個數
292      transpose:是否要轉置矩陣,並將它作為uniform變量的值。必須為GL_FALSE
293      value:執行count個元素的指針,用來更新指定uniform變量
294      */
295     glUniformMatrix4fv(projectionMatrixSlot, 1, GL_FALSE, (GLfloat*)&_projectionMatrix.m[0][0]);
296     
297 
298     // 3.創建一個4 * 4 矩陣,模型視圖矩陣
299     KSMatrix4 _modelViewMatrix;
300     //(1)獲取單元矩陣
301     ksMatrixLoadIdentity(&_modelViewMatrix);
302     //(2)平移,z軸平移-10
303     ksTranslate(&_modelViewMatrix, 0.0, 0.0, -10.0);
304     //(3)創建一個4 * 4 矩陣,旋轉矩陣
305     KSMatrix4 _rotationMatrix;
306     //(4)初始化為單元矩陣
307     ksMatrixLoadIdentity(&_rotationMatrix);
308     //(5)旋轉
309     ksRotate(&_rotationMatrix, xDegree, 1.0, 0.0, 0.0); //繞X軸
310     ksRotate(&_rotationMatrix, yDegree, 0.0, 1.0, 0.0); //繞Y軸
311     ksRotate(&_rotationMatrix, zDegree, 0.0, 0.0, 1.0); //繞Z軸
312     //(6)把變換矩陣相乘.將_modelViewMatrix矩陣與_rotationMatrix矩陣相乘,結合到模型視圖
313      ksMatrixMultiply(&_modelViewMatrix, &_rotationMatrix, &_modelViewMatrix);
314     //(7)將模型視圖矩陣傳遞到頂點着色器
315     /*
316      void glUniformMatrix4fv(GLint location,  GLsizei count,  GLboolean transpose,  const GLfloat *value);
317      參數列表:
318      location:指要更改的uniform變量的位置
319      count:更改矩陣的個數
320      transpose:是否要轉置矩陣,並將它作為uniform變量的值。必須為GL_FALSE
321      value:執行count個元素的指針,用來更新指定uniform變量
322      */
323     glUniformMatrix4fv(modelViewMatrixSlot, 1, GL_FALSE, (GLfloat*)&_modelViewMatrix.m[0][0]);
324 }
325 
326 // 加載紋理
327 - (void)loadTexture {
328     
329     // 9.0 image 轉為 CGImageRef
330     CGImageRef spriteImage = [UIImage imageNamed:@"0001"].CGImage;
331     // 圖片是否獲取成功
332     if (!spriteImage) {
333         NSLog(@"Failed to load image ");
334         return;
335     }
336     // 獲取圖片寬高
337     size_t width = CGImageGetWidth(spriteImage);
338     size_t height = CGImageGetHeight(spriteImage);
339     // 獲取圖片字節數 寬*高*4(RGBA)
340     GLubyte *spriteData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
341     
342     // 創建上下文
343     /*
344      data:指向要渲染的繪制圖像的內存地址
345      width:bitmap 的寬度,單位為像素
346      height:bitmap 的高度,單位為像素
347      bitPerComponent:內存中像素的每個組件的位數,比如 32 位 RGBA,就設置為 8
348      bytesPerRow:bitmap 的沒一行的內存所占的比特數
349      colorSpace:bitmap 上使用的顏色空間  kCGImageAlphaPremultipliedLast:RGBA
350      */
351     CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4,CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
352 
353     // 在 CGContextRef 上 --> 將圖片繪制出來
354     /*
355      CGContextDrawImage 使用的 Core Graphics 框架,坐標系與 UIKit 不一樣。UIKit 框架的原點在屏幕的左上角,Core Graphics 框架的原點在屏幕的左下角。
356      CGContextDrawImage(CGContextRef  _Nullable c, CGRect rect, CGImageRef  _Nullable image)
357      c:繪圖上下文
358      rect:rect坐標
359      image:繪制的圖片
360      */
361     CGRect rect = CGRectMake(0, 0, width, height);
362     CGContextDrawImage(spriteContext, rect, spriteImage);
363 
364     
365     // 翻轉圖片 方案一
366     // x、y 軸平移
367     CGContextTranslateCTM(spriteContext, rect.origin.x, rect.origin.y);
368     // y 平移
369     CGContextTranslateCTM(spriteContext, 0, rect.size.height);
370     // Y 軸方向 Scale -1 翻轉
371     CGContextScaleCTM(spriteContext, 1.0, -1.0);
372     // 平移回原點位置處
373     CGContextTranslateCTM(spriteContext, -rect.origin.x, -rect.origin.y);
374     // 重繪
375     CGContextDrawImage(spriteContext, rect, spriteImage);
376 
377     
378     // 繪完 釋放上下文
379     CGContextRelease(spriteContext);
380     
381     // 9.1. 綁定紋理到默認的紋理ID
382     glBindTexture(GL_TEXTURE_2D, 0);
383     
384     // 9.2. 設置紋理屬性
385     /*
386      glTexParameteri(GLenum target, GLenum pname, GLint param)
387      target:紋理維度
388      pname:線性過濾; 為s,t坐標設置模式
389      param:wrapMode; 環繞模式
390      */
391     // 過濾方式
392     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
393     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
394     // 環繞方式
395     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
396     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
397         
398     // 9.3 載入紋理
399     /* 載入紋理 glTexImage2D
400     參數1:紋理維度,GL_TEXTURE_2D
401     參數2:mip貼圖層次
402     參數3:紋理單元存儲的顏色成分(從讀取像素圖中獲得)
403     參數4:加載紋理寬度
404     參數5:加載紋理的高度
405     參數6:為紋理貼圖指定一個邊界寬度 0
406     參數7、8:像素數據的數據類型, GL_UNSIGNED_BYTE無符號整型
407     參數9:指向紋理圖像數據的指針
408     */
409     float fw = width, fh = height;
410     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
411 
412     // 9.4 釋放 sprite
413     free(spriteData);
414 }
415 
416 
417 
418 
419 // 加載着色器
420 // 頂點着色器 和 片元着色器 的代碼傳進來(.vsh  .fsh)
421 -(GLuint)loadShadersWithVertex:(NSString *)vert Withfrag:(NSString *)frag {
422     
423     // 1.定義 着色器
424     GLuint verShader, fragShader;
425     
426     // 2.創建程序 program
427     GLint program = glCreateProgram();// 創建一個空的程序對象
428     
429     // 3.編譯着色器 --> 封裝一個方法 compileShaderWithShader:
430     [self compileShaderWithShader:&verShader shaderType:GL_VERTEX_SHADER filePath:vert];
431     [self compileShaderWithShader:&fragShader shaderType:GL_FRAGMENT_SHADER filePath:frag];
432     
433     // 4.attach shader, 將shader附着到 程序
434     glAttachShader(program, verShader);
435     glAttachShader(program, fragShader);
436     
437     //5.已附着好的 shader 刪掉,避免不必要的內存占用
438     glDeleteShader(verShader);
439     glDeleteShader(fragShader);
440     
441     return program;// 返回編譯好的程序
442 }
443 // 編譯着色器
444 /*
445  shader: 着色器 ID
446  type: 着色器類型
447  path: 着色器代碼文件路徑
448  */
449 - (void)compileShaderWithShader:(GLuint *)shader shaderType:(GLenum)type filePath:(NSString *)path {
450     
451     // 1.讀取文件路徑
452     NSString *file = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
453     // NSString 轉 C 的 char
454     const GLchar *source = (GLchar *)[file UTF8String];
455     
456     // 2.創建對應類型的shader
457     *shader = glCreateShader(type);
458     
459     // 3.讀取着色器源碼 將其附着到着色器對象上面
460     /* params:
461      shader: 要編譯的着色器對象 *shader
462      numOfStrings: 傳遞的源碼字符串數量 1個
463      參數3:strings: 着色器程序的源碼(真正的着色器程序源碼)
464      參數4:lenOfStrings: 長度,具有每個字符串長度的數組,或NULL,這意味着字符串是NULL終止的
465      */
466     //    glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
467     glShaderSource(*shader, 1, &source,NULL);
468     
469     // 4. 編譯
470     glCompileShader(*shader);
471 }
472 
473 - (IBAction)rotClick:(UIButton *)sender {
474     
475     bX = bY = bZ = YES;
476     
477     myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(reDegree) userInfo:nil repeats:YES];
478 }
479 
480 
481 // 旋轉
482 -(void)reDegree {
483     
484     //如果停止X軸旋轉,X = 0則度數就停留在暫停前的度數.
485     //更新度數
486     xDegree += bX * 5;
487     yDegree += bY * 7;
488     zDegree += bZ * 9;
489     //重新渲染
490     [self renderLayer];
491     
492 }
493 
494 @end

着色器代碼:

 1 // 頂點着色器
 2 
 3 attribute vec4 position;
 4 attribute vec4 positionColor;
 5 
 6 uniform mat4 projectionMatrix;
 7 uniform mat4 modelViewMatrix;
 8 
 9 varying lowp vec4 varyColor;
10 
11 void main() {
12 
13     varyColor = positionColor;
14     
15     vec4 vPos;
16    
17     //4*4 * 4*4 * 4*1
18     vPos = projectionMatrix * modelViewMatrix * position;
19    
20     //ERROR
21     //vPos = position * modelViewMatrix  * projectionMatrix ;
22     gl_Position = vPos;
23 }
1 // 紋理着色器
2 varying lowp vec4 varyColor;
3 void main() {
4 
5     gl_FragColor = varyColor;
6 }

3.1、混合紋理

紋理加載代碼和之前Demo相同,不再贅述。

着色器代碼所需修改:

效果見下面效果動圖 

三、GLKit 索引繪圖繪制旋轉三角錐 - 顏色紋理混合

效果:

代碼:

  1 #import "ViewController.h"
  2 
  3 @interface ViewController () {
  4     
  5     dispatch_source_t timer;
  6 }
  7 
  8 @property (nonatomic, strong) EAGLContext *myContext;
  9 @property (nonatomic, strong) GLKBaseEffect *myEffect;
 10 
 11 // 旋轉的度數
 12 @property(nonatomic, assign) float XDegree;
 13 @property(nonatomic, assign) float YDegree;
 14 @property(nonatomic, assign) float ZDegree;
 15 
 16 @property(nonatomic, assign) int count;// 頂點個數
 17 
 18 @end
 19 
 20 @implementation ViewController
 21 
 22 - (void)viewDidLoad {
 23     [super viewDidLoad];
 24     // Do any additional setup after loading the view.
 25     
 26     // 新建圖層
 27     [self creatContext];
 28     
 29     // 渲染圖層
 30     [self render];
 31 }
 32 
 33 - (void)render {
 34     
 35     // 頂點數據
 36 //    // 3頂點 3顏色
 37 //    GLfloat attrArr[] = {
 38 //        -0.5f, 0.5f, 0.0f,      1.0f, 0.0f, 1.0f, //左上
 39 //        0.5f, 0.5f, 0.0f,       1.0f, 0.0f, 1.0f, //右上
 40 //        -0.5f, -0.5f, 0.0f,     1.0f, 1.0f, 1.0f, //左下
 41 //
 42 //        0.5f, -0.5f, 0.0f,      1.0f, 1.0f, 1.0f, //右下
 43 //        0.0f, 0.0f, 1.0f,       0.0f, 1.0f, 0.0f, //頂點
 44 //    };
 45     
 46     // 3頂點 3顏色 2紋理
 47     GLfloat attrArr[] = {
 48             -0.5f, 0.5f, 0.0f,      1.0f, 0.0f, 1.0f,       0.0f, 1.0f,//左上
 49             0.5f, 0.5f, 0.0f,       1.0f, 0.0f, 1.0f,       1.0f, 1.0f,//右上
 50             -0.5f, -0.5f, 0.0f,     1.0f, 1.0f, 1.0f,       0.0f, 0.0f,//左下
 51     
 52             0.5f, -0.5f, 0.0f,      1.0f, 1.0f, 1.0f,       1.0f, 0.0f,//右下
 53             0.0f, 0.0f, 1.0f,       0.0f, 1.0f, 0.0f,       0.5f, 0.5f,//頂點
 54         };
 55     
 56     // 繪圖索引數組
 57     GLuint indexes[] = {
 58         0, 3, 2,
 59         0, 1, 3,
 60         0, 2, 4,
 61         0, 4, 1,
 62         2, 3, 4,
 63         1, 4, 3,
 64     };
 65     self.count = sizeof(indexes) / sizeof(GLuint);//sizeof(indexes[0]);
 66     
 67     // 頂點數據copy到緩沖區
 68     GLuint attBuffer;
 69     glGenBuffers(1, &attBuffer);
 70     glBindBuffer(GL_ARRAY_BUFFER, attBuffer);
 71     glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_STATIC_DRAW);
 72     
 73     // 索引數據copy到緩沖區
 74     GLuint indexesBuffer;
 75     glGenBuffers(1, &indexesBuffer);
 76     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexesBuffer);
 77     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexes), indexes, GL_STATIC_DRAW);
 78     
 79     // 傳遞使用頂點數據
 80     glEnableVertexAttribArray(GLKVertexAttribPosition);
 81     glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, NULL);
 82     
 83     // 使用傳遞y顏色數據
 84     glEnableVertexAttribArray(GLKVertexAttribColor);
 85     glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, (GLfloat *)NULL + 3);
 86 
 87     // 紋理
 88     glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
 89     glVertexAttribPointer(GLKVertexAttribTexCoord0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 6);
 90     
 91     // 紋理圖片的讀取
 92     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"cat" ofType:@"jpg"];
 93     NSDictionary *option = @{GLKTextureLoaderOriginBottomLeft:@(YES)};
 94     GLKTextureInfo *info = [GLKTextureLoader textureWithContentsOfFile:filePath options:option error:nil];
 95     
 96     // 繪制
 97     self.myEffect = [[GLKBaseEffect alloc] init];
 98     // 紋理
 99     self.myEffect.texture2d0.enabled = YES;
100     self.myEffect.texture2d0.name = info.name;
101     
102     // 投影矩陣
103     float aspect = fabs(self.view.frame.size.width/self.view.frame.size.height);
104     GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 100.f);
105     // 投影矩陣 scale
106     projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0, 1.0, 1.0);
107     self.myEffect.transform.projectionMatrix = projectionMatrix;
108     
109     // 模型視圖矩陣
110     GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
111     self.myEffect.transform.modelviewMatrix = modelViewMatrix;
112     
113     
114     // GCD 定時器  - 旋轉
115     double seconds = 0.1;
116     timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
117     dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC, 0.0);
118     dispatch_source_set_event_handler(timer, ^{
119        
120         self.XDegree += 0.1f;
121         self.YDegree += 0.1f;
122         self.ZDegree += 0.1f;
123         
124     });
125     dispatch_resume(timer);
126 }
127 
128 - (void)creatContext {
129     
130     self.myContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
131 
132     // view
133     GLKView *kitView = (GLKView *)self.view;
134     kitView.context = self.myContext;
135     kitView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
136     kitView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
137     
138     // 設置當前上下文
139     [EAGLContext setCurrentContext:self.myContext];
140     
141     // 開啟深度測試
142     glEnable(GL_DEPTH_TEST);
143 }
144 
145 #pragma mark - GLKView delegate - 繪制 -
146 - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
147     
148     glClearColor(0.0, 0.3, 0.3, 1);
149     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
150     
151     [self.myEffect prepareToDraw];
152     glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0);
153     
154 }
155 // update - 旋轉
156 - (void)update {
157     
158     GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -3.0);
159     modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.XDegree);
160     modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, self.YDegree);
161     modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, self.ZDegree);
162 
163     self.myEffect.transform.modelviewMatrix = modelViewMatrix;
164 
165 }
166 
167 - (IBAction)rotClick:(UIButton *)sender {
168     
169 }
170 
171 
172 @end

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM