在上一节OpenGL的HelloWorld中,初步认识OpenGL,接着将对上节内容的中EAGLContext和GLKVertexAttribArrayBuffer进行封装,利用封装的函数减少应用需要调用OpenSE函数的数量,这同时也是减少缓存管理中的7个步骤相关的错误和代码的数量:
7个步骤:
- 生成(Generate)
- 绑定(Bind)
- 缓存数据(Buffer Data)
- 启用(Enable)或者禁用(Disable)
- 设置指针(Set Pointers)
- 绘图(Draw)
- 删除(Delete)
EAGLContext的封装类AGLKContext
这个相信不用注释一样能看得懂了~~~~
class AGLKContext: EAGLContext {
var clearColor: GLKVector4 {
set {
self.clearColor = newValue
glClearColor(
newValue.r,
newValue.g,
newValue.b,
newValue.a);
}
get {
return self.clearColor
}
}
func clear(mask: GLbitfield) {
glClear(mask);
}
func disable(capability: GLenum) {
glDisable(capability);
}
func enable(capability: GLenum) {
glEnable(capability);
}
func setBlendSourceFunction (sfactor: GLenum, dfactor: GLenum) {
glBlendFunc(sfactor, dfactor);
}
}
GLKVertexAttribArrayBuffer的封装类AGLKVertexAttribArrayBuffer
以下代码每一步都有相应的注释~~~~主要还是要考虑到代码的重用才进行封装。
enum AGLKVertexAttrib: GLuint {
case AGLKVertexAttribPosition = 0
case AGLKVertexAttribNormal = 1
case AGLKVertexAttribColor = 2
case AGLKVertexAttribTexCoord0 = 3
case AGLKVertexAttribTexCoord1 = 4
}
//封装顶点数组缓存
class AGLKVertexAttribArrayBuffer: NSObject {
//步幅,表示每个顶点需要多少个字节
var stride = GLsizei()
//缓存大小
var bufferSizeBytes = GLsizeiptr()
//缓存唯一标识
var bufferId = GLuint()
/**
创建顶点数组缓存
- parameter stride: 步幅
- parameter numberOfVertices: Vertices大小
- parameter bytes: Vertices内存地址
- parameter usage: 是否缓存在GPU
*/
func initWithAttribStride(stride: GLsizei, numberOfVertices: GLsizei, dataPtr: UnsafePointer<Void>, usage: GLenum) {
self.stride = stride
bufferSizeBytes = Int(stride) * Int(numberOfVertices);
glGenBuffers(1, &bufferId)
glBindBuffer(GLenum(GL_ARRAY_BUFFER), self.bufferId)
glBufferData(
GLenum(GL_ARRAY_BUFFER),
bufferSizeBytes,
dataPtr,
usage
)
}
//重新加载缓存数据
func reinitWithAttribStride(stride: GLsizei, numberOfVertices:GLsizei, dataPtr: UnsafePointer<Void>) {
self.stride = stride;
bufferSizeBytes = Int(stride) * Int(numberOfVertices);
glBindBuffer(GLenum(GL_ARRAY_BUFFER),
self.bufferId);
glBufferData(
GLenum(GL_ARRAY_BUFFER),
bufferSizeBytes,
dataPtr,
GLenum(GL_DYNAMIC_DRAW)
);
}
/**
Description
- parameter index: VertexAttrib
- parameter numberOfCoordinates: 坐标轴数
- parameter attribOffset: 从开始的每个顶点偏移
- parameter shouldEnable: 启用(Enable)或者禁用(Disable)
*/
func prepareToDrawWithAttrib(vertexAttrib: GLuint, numberOfCoordinates: GLint, attribOffset: GLsizeiptr, shouldEnable: Bool) {
glBindBuffer(GLenum(GL_ARRAY_BUFFER), self.bufferId);
if(shouldEnable)
{
glEnableVertexAttribArray(vertexAttrib)
}
glVertexAttribPointer(
vertexAttrib,
numberOfCoordinates, // 坐标轴数
GLenum(GL_FLOAT), // 数据类型
GLboolean(UInt8(GL_FALSE)),
self.stride,
nil + attribOffset); // 从开始的每个顶点偏移
}
//绘制图片
func drawArrayWithMode(mode:GLenum, startVertexIndex: GLint, numberOfVertices: GLsizei) {
glDrawArrays(mode, startVertexIndex, numberOfVertices);
}
//删除缓存
deinit {
if 0 != bufferId {
glDeleteBuffers (1, &bufferId);
bufferId = 0;
}
}
}
接口调用例子
self.vertextBuffer.initWithAttribStride(
GLsizei(sizeofValue(vertices[0])),
numberOfVertices: GLsizei(vertices.count),
dataPtr: vertices,
usage:GLenum(GL_STATIC_DRAW)
)
self.vertextBuffer.prepareToDrawWithAttrib(
AGLKVertexAttrib.AGLKVertexAttribPosition.rawValue,
numberOfCoordinates: 3,
attribOffset:0,
shouldEnable: true
)
self.vertextBuffer.drawArrayWithMode(
GLenum(GL_TRIANGLE_FAN),
startVertexIndex: 0,
numberOfVertices:
GLsizei(vertices.count)
)
详细的的调用例子请参看源码。
源码点这里,喜欢就关注吧,持续更新中。