第一个 OpenGL ES的小程序(过程写的非常详细)

来源:互联网 发布:王震对新疆的功过知乎 编辑:程序博客网 时间:2024/04/23 22:30
#import"King_ViewController.h"


@interface King_ViewController()


@end


@implementationKing_ViewController

@synthesize baseEffect;


//这个数据类型用于储存每个定点的位置信息

typedef struct{

   GLKVector3 positionCoords;

    

}SceneVerTex;

//声明在demo中三角形定点数据静态变量这个例子中得顶点坐标是挑选出来的,因为默认的用于一个OpenGL上下文的可见坐标系是分别沿着X YZ轴从-1.01.0的。例子中的三角形坐标把它置于可见坐标系的中央并且与XY 所形成的平面对齐。

staticconst SceneVerTex vertices[] =

{

    {{-0.5f,-0.5f,0.0f}},

    {{0.5f,-0.5f,0.0f}},

   {{-0.5f,0.5f,0.0f}}

};


- (void)viewDidLoad

{

    

   NSLog(@"%s",__func__);

   [superviewDidLoad];

// Do any additional setup after loading the view, typically from anib.

  //将她继承的view属性的类型转换成GLKview类型。类似GLKVeiwController的子类之恩能够与GLKVie实例或者其子类的实例一起正常工作。

   GLKView * view = (GLKView * )self.view;

    

  //断言检查storyboard加载的的视图是否确实是正确的类型。错误会抛出NSInternal--tion:内部不匹配异常

   NSAssert([viewisKindOfClass:[GLKViewclass]], @"view controller's view is not aGLKview");

    

  //分配并初始化一个内奸的EAGLContext类的实例izhege实例会封装一个特定于某个平台的OpenGLES上下文。OpenGL的上下文不仅会保存OpenGLES的状态,还会控制GPU去执行渲染运算。

   view.context= [[EAGLContext  alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    

  //在任何其他的OpenGLES配置或渲染发生之前,应用得GLKView实例的上下文属性都需要设置为当前。EAGLContext实例即支持OpenGLES1.1,又支持OpenGLES2.0。本例使用的是2.0版本(苹果建议使用2.0:灵活性)。

   [EAGLContext setCurrentContext:view.context];

    

  //实例化基础效果实例,如果没有GLKitGLKBaseEffect类,就需要为这个简单的例子编写一个小的GPU程序,使用2.0ShadingLanguage,而GLKBaseEffect会在需要的时候自动的构建GPU程序并极大地简化本例。

   self.baseEffect = [[GLKBaseEffectalloc] init];

   self.baseEffect.useConstantColor= GL_TRUE;

    

  //控制渲染像素颜色的方式有多种。这个应用的GLKBaseEffect实例使用一个恒定不变的白色来渲染三角形。

  //下面代码中使用的再GLKit中定义的用于保存4个颜色元素值的C数据结构体GLKVector4来设置这个恒定值。

   self.baseEffect.constantColor =GLKVector4Make(1.0f,1.0f, 1.0f,1.0f);

    

  //glClearColor函数设置当前glClearColor上下文的清除颜色为不透明黑色。清除颜色由RGBA颜色元素值组成,用于在上下文的帧缓存被清除时初始化每个像素的颜色值。

   glClearColor(0.0f,0.0f, 0.0f, 1.0f);

    

  //为缓存生成一个独一无二的标示符 step1

  //函数解析 :第一个参数用于指定要生成的缓存标示符的数量,第二个参数是一个指针,指向生成标示符的内存保存位置。

  //在当前情况下,一个标示符被生成,保存在vertexBufferID成员变量中

   glGenBuffers(1,&vertexBufferID);

    

   //为接下来的运算绑定缓存  step2

  //glBindBuffer函数绑定用于指定标示符的缓存到当前缓存。但是在任意时刻每种类型只能绑定一个缓存。如果在这个例子中使用了两个顶点属性的数字缓存,那么同一时刻不能被绑定。

  //第一个参数是一个常量,用于指定要绑定哪一种类型的缓存。OpenGLES2.0目前只支持两种类型的缓存。GL_ELEMENT_ARRAY_BUFFERGL_ARRAY_BUFFERGL_ARRAY_BUFFER类型用于指定一个顶点属性的数组,例如,本例中三角形定点的位置。第二个参数是要绑定的缓存的标示符。

   glBindBuffer(GL_ARRAY_BUFFER,vertexBufferID);

    

    

   //复制数据到缓存中    step3

  //glBufferData函数复制应用的额顶点数据到当前上下文所绑定的顶点缓存中。

  //第一个参数用于指定要更新当前上下文中所绑定的时哪一个缓存。

  //第二个参数指定要复制进这个缓存的自己的数量。

  //第三个参数是要复制的字节的地址

  //第四个参提示了在未来的运算中可能被怎样运用

  //GL_STATIC_DRAW提示告诉上下文,缓存中的内容适合复制到GPU控制的内存,因为很少对齐进行修改。这个信息可帮助OpenGLES优化内存使用。

  //GL_DYNAMIC_DRAW 提示数据会频繁改变,同时提示ES以不同的方式处理缓存中得存储。

   glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices, GL_STATIC_DRAW);

    

}


//此委托方法的实现告诉baseEffect装备好当前的OpenGLES的上下文,一边为使用baseEffect生成的属性和ShadingLanguage程序的绘画做好准备。

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect

{

   NSLog(@"%s",__func__);

    

   //

   [self.baseEffect prepareToDraw];

    

  //glClear函数设置当前绑定的帧缓存的像素颜色渲染缓存中的每一个能有除了像素颜色缓存之外的其他附加的缓存,并且如果其他的缓存被使用了,他们可通过在函数中指定不懂得参数来消除。glClear函数会有效地设置帧缓存中每一个像素的颜色为背景颜色。

   glClear(GL_COLOR_BUFFER_BIT);

    

    

   //glEnableVertexAttribArray 启动定点缓存渲染操作。step 4

   glEnableVertexAttribArray(GLKVertexAttribPosition);

    

   //glVertexAttribPointer 函数会告诉OpenGL ES 定点数据在哪里,以及解释为每个顶点保存的数据。step 5

  //第一个参数指示当前绑定的缓存包含每个定点的位置信息

  //第二个参数指示每个顶点位置有三个组成部分

  //第三个参数告诉ES每个部分都保存为一个浮点类型的值

  //第四个参数告诉ES小数点固定数据是否可以被改变。 没有使用所以用GL_FALSE

  //第五个参数叫做步幅,他指定了每个订单的保存需要多少个字节。

  //最后一个参数NULL,这告诉OpenGLES可以从当前绑定的定点缓存的开始位置访问定点数据。

   glVertexAttribPointer(GLKVertexAttribPosition,3,GL_FLOAT,GL_FALSE, sizeof(SceneVerTex),NULL);

   //

   //调用glDrawArrays执行绘图。step 6

  //第一个参数告诉GPU怎么处理绑定的顶点缓存内的顶点数据。

  //第二个和第三个分别制定缓存内的需要渲染的第一个顶点的位置,炫耀渲染的顶点的数量。

   glDrawArrays(GL_TRIANGLES,0,3);

    

  //至此,例子中显示的场景已经被完全的渲染出来了,cpugpu的运算是一部的。这个例子中所有代码都是运行在cpu上的。然后在需要进一步处理的时候向gpu发送命令。gpu可能也会处理发送自ioscoreanimation的命令。因此在任何给定时刻gpu总公钥执行多少处理并不一定。

}



//视图被最终卸载时调用。卸载的试图将不再被绘制,因此任何指示再回只是需要的OpenGLES 缓存都可以被安全的删除。

-(void)viewDidUnload

{

   NSLog(@"%s",__func__);


   [superviewDidUnload];


   // 删除不再需要的定点缓存和上下文。step 7    

   GLKView * view = (GLKView *)self.view;

   [EAGLContext setCurrentContext:view.context];

    

  //设置vertexBufferID0避免了在对应的缓存被删除以后还是勇气无效的标示符。

   if(0!=vertexBufferID) {

      glDeleteBuffers(1,&vertexBufferID);

       vertexBufferID=0;

    }

  //设置视图的上下文属性为nil,并设置当前上下文为nil。以便让ios收回所有上下文使用的内存和其他资源。

   ((GLKView *)self.view).context= nil;

   [EAGLContextsetCurrentContext:nil];

}


来源:http://blog.sina.com.cn/s/blog_b0c5954101019ers.html


0 0
原创粉丝点击