与用固定着色器绘制三角形类似,这里重点讲下不同的地方。
1.加载图片
- (void)setupTexture {
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"triangle.png" ofType:nil];
// GLKTextureLoaderOriginBottomLeft 表示是否需要翻转图片以适配OpenGL坐标系(UIKIt坐标原点在左上方,OpenGL原点在左下方)
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:@{GLKTextureLoaderOriginBottomLeft : @YES} error:nil];
_effect.texture2d0.name = textureInfo.name;
_effect.texture2d0.target = textureInfo.target;
}
2.设置顶点数据
- (void)setupVertexBuffer {
// 顶点数据(顶点坐标 + 纹理坐标)
SceneVertex vertices[] = {
// N 形
// { {-0.5, 0.5, 0}, {0, 1} },
// { {-0.5, -0.5, 0}, {0, 0} },
// { {0.5, 0.5, 0}, {1, 1} },
// { {0.5, -0.5, 0}, {1, 0} },
// Z 形
{ {-0.5, 0.5, 0}, {0, 1} },
{ {0.5, 0.5, 0}, {1, 1} },
{ {-0.5, -0.5, 0}, {0, 0} },
{ {0.5, -0.5, 0}, {1, 0} },
// 未重复利用
// { {-0.5, 0.5, 0}, {0, 1} },
// { {-0.5, -0.5, 0}, {0, 0} },
// { {0.5, 0.5, 0}, {1, 1} },
// { {-0.5, -0.5, 0}, {0, 0} },
// { {0.5, -0.5, 0}, {1.0, 0} },
// { {0.5, 0.5, 0}, {1, 1} },
};
// 操作顶点缓存区 (GPU)
glGenBuffers(1, &_vertextBufferID);
// 1.绑定顶点到缓存区,将attrBuffer绑定到GL_ARRAY_BUFFER标识符上
glBindBuffer(GL_ARRAY_BUFFER, _vertextBufferID);
// 2.拷贝数据到顶点缓存区上 cpu内存 -> gpu显存
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 在iOS中,系统处于性能考虑,默认所有的顶点着色器的属性(Attribute)通道都是关闭的,需要开启后才能操作数据
// 1.打开顶点坐标通道
glEnableVertexAttribArray(GLKVertexAttribPosition);
/**
glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
上传顶点数据到显存的方法
@param indx GLKVertexAttrib枚举值
@param size 每次读取的数量,比如position是由3个坐标组成(x,y,z),颜色是由4个组成(r,g,b,a) 纹理则两个(s,t)
@param type 数组中每个顶点的数据类型(GL_FLOAT、GL_SHORT、GL_BYTE、GL__UNSIGNED_BYTE等)
@param normalized 顶点数据是否需要被归一化
@param stride 指定连续顶点属性之间的偏移量(读取步长)。如果为0,那么顶点属性会被理解为:他们是紧密排在一起的。初始值为0
@param ptr 指定一个指针,指向数组中第一个顶点属性的第一个组件。初始值为0
*/
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(SceneVertex) , NULL + offsetof(SceneVertex, positionCoords));
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL + offsetof(SceneVertex, textureCoord));
}