注:本文旨在记录笔者的学习过程,仅代表笔者个人的理解,如果有表述不准确的地方,欢迎各位指正!因为涉及到的概念来源自网络,所以如有侵权,也望告知!
前言
本文主要目的是基于GLKit实现索引绘图,纹理颜色的混合。
正文
GLKit介绍
GLKit 框架的设计⽬标是为了简化基于OpenGL / OpenGL ES 的应⽤开发。它的出现加快OpenGL ES或OpenGL应⽤程序开发。 使⽤数学库,背景纹理加载,预先创建的着⾊器效果,以及标准视图和视图控制器来实现渲染循环。GLKit框架提供了功能和类,可以减少创建新的基于着⾊器的应⽤程序所需的⼯作量,或者⽀持依赖早期版本的OpenGL ES或OpenGL提供的固定函数顶点或⽚段处理的现有应⽤程序。
GLKit实践
1.配置GLKit视图
使用GLKit来进行图形绘制时,我们需要具备以下两个条件:
首先,项目中的控制器需要继承GLKViewController。
其次,控制器的对应的view需要是GLKView的实例。
那么这两个类到底是什么作用呢?
GLKView:提供绘制场所。
GLKViewController:扩展于标准的UIKit 设计模式,⽤于绘制视图内容的管理与呈现。
2.创建上下文
GLKit视图配置完成之后,我们需要创建一个OpenGL ES上下文,并设置为当前有效。
-(void)setupContext {
//1.新建OpenGL ES上下文
self.mContext = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
GLKView *view = (GLKView *)self.view;
view.context = self.mContext;
view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
[EAGLContext setCurrentContext:self.mContext];
glEnable(GL_DEPTH_TEST);
}
3.设置渲染数据
OpenGL ES上下文设置完成后,我们就可以进一步设置顶点数据、绘图索引数据、顶点颜色数据。
顶点数据:
/顶点数据
//前3个元素,是顶点数据;后3个元素,是顶点颜色值
GLfloat attrArr[] =
{
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f,//左上
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f,//右上
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f,//左下
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f,//右下
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,//顶点
};
//将顶点数组放入数组缓冲区中 GL_ARRAY_BUFFER
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_STATIC_DRAW);
绘图索引数据:
//绘图索引
GLuint indices[] =
{
0, 3, 2,
0, 1, 3,
0, 2, 4,
0, 4, 1,
2, 3, 4,
1, 4, 3,
};
//将索引数组存储到索引缓冲区 GL_ELEMENT_ARRAY_BUFFER
GLuint index;
glGenBuffers(1, &index);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
问:为什么使用索引绘图?
答:通过索引绘图可以对重复的顶点进行复用。
问:如何实现的?
设置数据:
//使用顶点数据
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, NULL);
//使用颜色数据
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (GLfloat *)NULL + 3);
4.设置固定着色器GLKBaseEffect
GLKit通过固定着色器GLKBaseEffect来进行绘制,通过GLKBaseEffect我们可以设置投影矩阵、模型视图矩阵。
//着色器
self.mEffect = [[GLKBaseEffect alloc]init];
//投影视图
CGSize size = self.view.bounds.size;
float aspect = size.width / size.height;
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 100.0);
projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0f, 1.0f, 1.0f);
self.mEffect.transform.projectionMatrix = projectionMatrix;
//模型视图
GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
self.mEffect.transform.modelviewMatrix = modelViewMatrix;
5.完成图形绘制
GLKit绘制会通过代理方法- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect;进行回调,我们需要在代理中完成最终的绘制。
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[self.mEffect prepareToDraw];
glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0);
}
6.纹理添加,与颜色进行混合
通过索引绘图完成图形的绘制流程后,我们现在需要调整一下代码,将我们的纹理加载上去。
顶点数据调整:
//顶点数据
//前3个元素,是顶点数据;中间3个元素,是顶点颜色值,最后2个是纹理坐标
GLfloat attrArr[] =
{
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,//左上
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,//右上
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,//左下
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,//右下
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f,//顶点
};
设置数据调整:
//使用顶点数据
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, NULL);
//使用颜色数据
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 3);
加载纹理数据:
//使用纹理坐标数据
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 6);
//获取纹理路径
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"kunkun" ofType:@"jpg"];
//加载纹理
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@"1",GLKTextureLoaderOriginBottomLeft, nil];
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
固定着色器调整:
//着色器
self.mEffect = [[GLKBaseEffect alloc]init];
self.mEffect.texture2d0.enabled = GL_TRUE;
self.mEffect.texture2d0.name = textureInfo.name;