*********************************************************************************************************************************************************************
转载需要注明出处,博客将持续更新,刚开始在CSDN上写技术博客,欢迎大家提宝贵意见
--presented by luo
*********************************************************************************************************************************************************************
本文将和大家分享,如何在iOS上创建第一个OpenGL程序,这里我们是创建一个最简单的OpenGL ES 图元——三角形
基本步骤:
1. 导入创建OpenGL-ES project所需要的framework
创建OpenGL ES project 需要用到的framework有: OpenGLES.framework , QuartzCore.framework, GLKit.framework,UIKit.frame, Foundation.framework and CoreGraphics.framework。
2. 创建一个继承自UIViewController的ViewController,这里我取名为OpenGLViewController,
在头文件中做如下修改:
#import
@interfaceOpenGLViewController :GLKViewController
{
//盛放顶点数据的buffer的OpenGL ES标识符
GLuint vertexBufferID; //typedef unsigned int GLuint;
}
//设置一个GLKBaseEffect(通用着色器)的属性特性
@property (strong,nonatomic)GLKBaseEffect *baseEffect;
3. 在实现文件中,需要做的工作详细叙述如下:
3.1 创建3D顶点数据
typedefstruct
{
GLKVector3 positionCoords;
} SceneVertex;
staticconstSceneVertex vertices[] =
{
{{-0.5f,-0.5f, 0.0}},
{{0.5f, -0.5f, 0.0}},
{{-0.5f, 0.5f, 0.0}}
};
这里附上GLKVector3的定义:
union _GLKVector3
{
struct{ float x, y, z; };
struct{ float r, g, b; };
struct { float s, t, p; };
floatv[3];
};
typedefunion _GLKVector3 GLKVector3;
3.2 重写 – (void) viewDidLoad
- (void)viewDidLoad
{
[superviewDidLoad];
//转换当前View为GLKView类型,GLK前缀表明该类来自GLKit框架的类
GLKView *view =(GLKView *)self.view;
//使用断言(Assert)来调试程序,下面语句的意思是:如果[viewisKindOfClass:[GLKView class]]非真,则输出Viewcontroller's view is not a GLKView信息。
NSAssert([viewisKindOfClass:[GLKViewclass]],@"Viewcontroller's view is not a GLKView");
//产生一个OpenGL ES context实例并将它提供给当前视图
view.context = [[EAGLContextalloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
view.delegate =self;
//EAGL:苹果并没有说明代表什么,可能代表“Emabled Apple GL”,这里+setCurrentContext是一个类方法(即没有实例仍可以被自身调用的方法),该方法会为接下来的OpenGL ES运算设置将会用到的context
[EAGLContextsetCurrentContext:view.context];
//设置颜色,baseEffect是一个通用着色器,为后续的呈现着色
//初始化一个着色器
self.baseEffect = [[GLKBaseEffectalloc]init];
// Contant: 常量
self.baseEffect.useConstantColor =GL_TRUE;
//将context后续呈现着色为白色,你可以根据红绿蓝三基色调成不同的颜色
self.baseEffect.constantColor = GLKVector4Make(1.0f, 1.0f, 1.0f, 1.0f);
//设置当前OpenGLES的context的“clearColor”。
glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
/*
接下来,是整个工作的重点,设置buffer, buffer用于在CPU控制的内存和GPU控制的内存之间交换数据。创建并使用一个用于保存*顶点数据*的*顶点属性数组buffer*(VertexAttribArray Buffer),整个过程分为7步进行
*/
//第一步:为buffer生成一个独一无二的标识符;
对于glGenBuffers的两个参数: 1. 第一个参数用于指定要生成的buffer标识符的数量,第二个参数是一个指针,指向生成的标识符的内存保存位置
glGenBuffers(1, &vertexBufferID);
//第二步: 为接下来的运算绑定缓存
对于管理BindBuffer的两个参数:1. 第一个参数是一个常量,用于指定要绑定哪种类型的缓存,OpenGL ES 2.0 对于glBindBuffer()的实现只支持两种类型的缓存GL_ARRAY_BUFFER和GL_ELEMENT_ARRAY_BUFFER。第二个参数是要绑定的标识符
glBindBuffer(GL_ARRAY_BUFFER,vertexBufferID);
//第三步:复制数据到buffer中
glBufferData(GL_ARRAY_BUFFER, //参数1:指定要更新当前上下文中所绑定的是哪一个缓存
sizeof(vertices), //参数2:指定要复制进这个缓存的的字节数
vertices, //参数3:指定要复制的字节的地址
GL_STATIC_DRAW); //参数4:提示了缓存在未来的运算中可能将会被怎样使用,GL_STATIC_DRAW提示会告诉context,缓存的内容适合复制到GPU控制的内存,因为很少对其进行修改,这个信息可以帮助OpenGL-ES优化内存使用,而使用GL_DYNAMIC_DRAW作为提示会告诉context,缓存内的数据会频繁改变,同时提示OpenGLES以不同的方式来处理缓存的存储
}
//接下来的对buffer进行的四步操作,将会在GLKView的Delegate方法中实现
#pragma mask Delegate Method
- (void)glkView:(GLKView *)viewdrawInRect:(CGRect)rect
{
//前面已经在viewDidLoad中实现了三个step,接下来在委托中还要实现三个step,其分别是4)启动;5)设置指针;6)绘图。
[self.baseEffectprepareToDraw];
glClear(GL_COLOR_BUFFER_BIT); //用于设置当前绑定的桢缓存的像素颜色渲染缓存中的每一个像素的颜色为当前使用的glClearColor()函数设定的值
// 第四步: 启动
glEnableVertexAttribArray(GLKVertexAttribPosition);//启动顶点缓存渲染操作,OpenGLES所支持的每一个渲染操作都可以单独地使用保存在当前OpenGLES context中的设置来开启和关闭
//第五步:设置指针
//下面这个函数会告诉OpenGLES顶点数据在哪里,以及怎么解释为每一个顶点保存数据
glVertexAttribPointer(GLKVertexAttribPosition, //第一个参数指定当前绑定的缓存包含每个顶点的位置信息
3, //第二个参数指示每个位置由3个部分组成
GL_FLOAT, //告诉OpenGL ES每个部分都保存为一个浮点类型的值
GL_FALSE, //OpenGL ES小数点固定数据是否可以被改变
sizeof(SceneVertex), //步长:指定了每个顶点的保存需要多少个字节,换句话说,步长指定了GPU从一个顶点的内存开始位置转到下一个顶点的内存开始位置需要跳过多少字节。
NULL); //OpenGL ES可以从当前绑定的顶点缓存的开始位置访问顶点数据
//第六步:绘图
//下面这个函数用来执行绘图
glDrawArrays(GL_TRIANGLES, //第一个参数会告诉GPU怎么处理在绑定的顶点缓存内的顶点数据,这里是渲染一个三角形
0, //指定需要渲染的第一个顶点的位置
3); //需要渲染的顶点的个数
}
//
- (void)viewDidUnload
{
[superviewDidUnload];
// Make the view's context current
GLKView *view = (GLKView *)self.view;
[EAGLContextsetCurrentContext:view.context];
//第七步:删除不再需要的顶点buffer和context
// Delete buffers that aren't needed whenview is unloaded
if (0 !=vertexBufferID)
{
glDeleteBuffers (1, // STEP 7
&vertexBufferID);
vertexBufferID = 0;
}
// Stop using the context created in-viewDidLoad
((GLKView *)self.view).context = nil;
[EAGLContextsetCurrentContext:
}
4. 就这样,整个过程实现了一个完整的OpenGL ES程序。
如果你不喜欢打字,或者你依照教程一步一步的写下来却无法得到正确的结果,你可以通过下面的链接下载本程序的源码:
http://download.csdn.net/detail/luozhonglan/6985779
**************************************************************************************************************
祝大家新年快乐
——罗大柚
**************************************************************************************************************