iOS开发——图形编程OC篇&OpenGL ES2.0编程步骤

OpenGL ES2.0编程步骤

OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。

1. 保存全局变量的数据结构

以下例子程序均基于Linux平台。

 1 typedef struct _escontext
 2 {
 3    void*       userData;                    // Put your user data here...
 4    GLint       width;                          // Window width
 5    GLint       height;                         // Window height
 6    EGLNativeWindowType  hWnd;  // Window handle
 7    EGLDisplay  eglDisplay;             // EGL display
 8    EGLContext  eglContext;            // EGL context
 9    EGLSurface  eglSurface;            // EGL surface
10
11    // Callbacks
12    void (ESCALLBACK *drawFunc) ( struct _escontext * );
13    void (ESCALLBACK *keyFunc) ( struct _escontext *, unsigned char, int, int );
14    void (ESCALLBACK *updateFunc) ( struct _escontext *, float deltaTime );
15 }ESContext;
 1 typedef struct
 2 {
 3    // Handle to a program object
 4    GLuint programObject;
 5
 6    // Atrribute Location
 7    GLint positionLoc;
 8    GLint textureLoc;
 9
10    // Uniform location
11    GLint matrixModeLoc;
12    GLint matrixViewLoc;
13    GLint matrixPerspectiveLoc;
14
15    // Sampler location
16    GLint samplerLoc;
17
18    // texture
19    GLuint texture;
20 } UserData;

2. 初始化EGL渲染环境和相关元素(第一步曲)

 1 int InitEGL(ESContext * esContext)
 2 {
 3      NativeWindowType eglWindow = NULL;
 4
 5      EGLDisplay display;
 6      EGLContext context;
 7      EGLSurface surface;
 8
 9      EGLConfig configs[2];
10      EGLBoolean eRetStatus;
11      EGLint majorVer, minorVer;
12      EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
13
14      EGLint numConfigs;
15      EGLint cfg_attribs[] = {EGL_BUFFER_SIZE,    EGL_DONT_CARE,
16                              EGL_DEPTH_SIZE,     16,
17                              EGL_RED_SIZE,       5,
18                              EGL_GREEN_SIZE,     6,
19                              EGL_BLUE_SIZE,      5,
20                              EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
21                              EGL_NONE};
22
23      // Get default display connection
24      display = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
25      if ( display == EGL_NO_DISPLAY )
26      {
27           return EGL_FALSE;
28      }
29
30      // Initialize EGL display connection
31      eRetStatus = eglInitialize(display, &majorVer, &minorVer);
32      if( eRetStatus != EGL_TRUE )
33      {
34           return EGL_FALSE;
35      }
36
37      //Get a list of all EGL frame buffer configurations for a display
38      eRetStatus = eglGetConfigs (display, configs, 2, &numConfigs);
39      if( eRetStatus != EGL_TRUE )
40      {
41           return EGL_FALSE;
42      }
43
44      // Get a list of EGL frame buffer configurations that match specified attributes
45      eRetStatus = eglChooseConfig (display, cfg_attribs, configs, 2, &numConfigs);
46      if( eRetStatus != EGL_TRUE  || !numConfigs)
47      {
48           return EGL_FALSE;
49      }
50
51      // Create a new EGL window surface
52      surface = eglCreateWindowSurface(display, configs[0], eglWindow, NULL);
53      if (surface == EGL_NO_SURFACE)
54      {
55           return EGL_FALSE;
56      }
57
58      // Set the current rendering API (EGL_OPENGL_API, EGL_OPENGL_ES_API,EGL_OPENVG_API)
59      eRetStatus = eglBindAPI(EGL_OPENGL_ES_API);
60      if (eRetStatus != EGL_TRUE)
61      {
62           return EGL_FALSE;
63      }
64
65      // Create a new EGL rendering context
66      context = eglCreateContext (display, configs[0], EGL_NO_CONTEXT, context_attribs);
67      if (context == EGL_NO_CONTEXT)
68      {
69           return EGL_FALSE;
70      }
71
72      // Attach an EGL rendering context to EGL surfaces
73      eRetStatus = eglMakeCurrent (display, surface, surface, context);
74      if( eRetStatus != EGL_TRUE )
75      {
76           return EGL_FALSE;
77      }
78      //If interval is set to a value of 0, buffer swaps are not synchronized to a video frame, and the swap happens as soon as the render is complete.
79      eglSwapInterval(display,0);
80
81      // Return the context elements
82      esContext->eglDisplay = display;
83      esContext->eglSurface = surface;
84      esContext->eglContext = context;
85
86      return EGL_TRUE;
87 }

3. 生成Program (第二步曲)

3.1 LoadShader

LoadShader主要实现以下功能:

1) 创建Shader对象

2) 装载Shader源码

3) 编译Shader

其实现参考代码如下:

 1 /* type specifies the Shader type: GL_VERTEX_SHADER or GL_FRAGMENT_SHADER */
 2 GLuint LoadShader ( GLenum type, const char *shaderSrc )
 3 {
 4    GLuint shader;
 5    GLint compiled;
 6
 7    // Create an empty shader object, which maintain the source code strings that define a shader
 8    shader = glCreateShader ( type );
 9
10    if ( shader == 0 )
11        return 0;
12
13    // Replaces the source code in a shader object
14    glShaderSource ( shader, 1, &shaderSrc, NULL );
15
16    // Compile the shader object
17    glCompileShader ( shader );
18
19    // Check the shader object compile status
20    glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
21
22    if ( !compiled )
23    {
24       GLint infoLen = 0;
25
26       glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
27
28       if ( infoLen > 1 )
29       {
30          char* infoLog = malloc (sizeof(char) * infoLen );
31
32          glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
33          esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
34
35          free ( infoLog );
36       }
37
38       glDeleteShader ( shader );
39       return 0;
40    }
41
42    return shader;
43 }

1)glCreateShader
       它创建一个空的shader对象,它用于维护用来定义shader的源码字符串。支持以下两种shader:
      (1) GL_VERTEX_SHADER: 它运行在可编程的“顶点处理器”上,用于代替固定功能的顶点处理;
      ( 2) GL_FRAGMENT_SHADER: 它运行在可编程的“片断处理器”上,用于代替固定功能的片段处理;

2)glShaderSource
        shader对象中原来的源码全部被新的源码所代替。

3)glCompileShader
       编译存储在shader对象中的源码字符串,编译结果被当作shader对象状态的一部分被保存起来,可通过glGetShaderiv函数获取编译状态。

4)glGetShaderiv
       获取shader对象参数,参数包括:GL_SHADER_TYPE, GL_DELETE_STATUS, GL_COMPILE_STATUS, GL_INFO_LOG_LENGTH, GL_SHADER_SOURCE_LENGTH.

3.2 LoadProgram

其参考代码如下:

 1 GLuint LoadProgram ( const char *vShaderStr, const char *fShaderStr )
 2 {
 3    GLuint vertexShader;
 4    GLuint fragmentShader;
 5    GLuint programObject;
 6    GLint linked;
 7
 8    // Load the vertex/fragment shaders
 9    vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
10    fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
11
12    // Create the program object
13    programObject = glCreateProgram ( );
14    if ( programObject == 0 )
15       return 0;
16
17    // Attaches a shader object to a program object
18    glAttachShader ( programObject, vertexShader );
19    glAttachShader ( programObject, fragmentShader );
20    // Bind vPosition to attribute 0  
21    glBindAttribLocation ( programObject, 0, "vPosition" );
22    // Link the program object
23    glLinkProgram ( programObject );
24
25    // Check the link status
26    glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
27
28    if ( !linked )
29    {
30       GLint infoLen = 0;
31
32       glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
33
34       if ( infoLen > 1 )
35       {
36          char* infoLog = malloc (sizeof(char) * infoLen );
37
38          glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
39          esLogMessage ( "Error linking program:\n%s\n", infoLog );
40
41          free ( infoLog );
42       }
43
44       glDeleteProgram ( programObject );
45       return GL_FALSE;
46    }
47
48    // Free no longer needed shader resources
49    glDeleteShader ( vertexShader );
50    glDeleteShader ( fragmentShader );
51
52    return programObject;
53 }

1)glCreateProgram
      建立一个空的program对象,shader对象可以被连接到program对像
2)glAttachShader
      program对象提供了把需要做的事连接在一起的机制。在一个program中,在shader对象被连接在一起之前,必须先把shader连接到program上。
3)glBindAttribLocation
       把program的顶点属性索引与顶点shader中的变量名进行绑定。
4)glLinkProgram
      
连接程序对象。如果任何类型为GL_VERTEX_SHADER的shader对象连接到program,它将产生在“可编程顶点处理器”上可执行的程
序;如果任何类型为GL_FRAGMENT_SHADER的shader对象连接到program,它将产生在“可编程片断处理器”上可执行的程序。
5)glGetProgramiv
       获取program对象的参数值,参数有:GL_DELETE_STATUS, GL_LINK_STATUS,
GL_VALIDATE_STATUS, GL_INFO_LOG_LENGTH, GL_ATTACHED_SHADERS,
GL_ACTIVE_ATTRIBUTES, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
GL_ACTIVE_UNIFORMS, GL_ACTIVE_UNIFORM_MAX_LENGTH.

3.3 CreateProgram

在3.1中只实现了Shader的编译,在3.2中只实现了Program的链接,现在还缺少真正供进行编译和链接的源码,其参考代码如下:

 1 int CreateProgram(ESContext * esContext)
 2 {
 3      GLuint programObject;
 4
 5      GLbyte vShaderStr[] =
 6       "attribute vec4 vPosition;    \n"
 7       "void main()                  \n"
 8       "{                            \n"
 9       "   gl_Position = vPosition;  \n"
10       "}                            \n";
11
12      GLbyte fShaderStr[] =
13       "precision mediump float;\n"14       "void main()                                  \n"
15       "{                                            \n"
16       "  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
17       "}                                                    \n";
18
19     // Create user data
20     esContext->userData = malloc(sizeof(UserData));
21     UserData *userData = esContext->userData;
22
23     // Load the shaders and get a linked program object
24     programObject = LoadProgram ( (const char*)vShaderStr, (const char*)fShaderStr );
25     if(programObject == 0)
26     {
27     return GL_FALSE;
28     }
29
30     // Store the program object
31     userData->programObject = programObject;
32
33     // Get the attribute locations
34     userData->positionLoc = glGetAttribLocation ( g_programObject, "v_position" );
35     glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
36     return 0;
37 }

4. 安装并执行Program(第三步)

 1 void Render ( ESContext *esContext )
 2 {
 3    UserData *userData = esContext->userData;
 4    GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
 5                            -0.5f, -0.5f, 0.0f,
 6                             0.5f, -0.5f, 0.0f };
 7
 8    // Set the viewport
 9    glViewport ( 0, 0, esContext->width, esContext->height );
10
11    // Clear the color buffer
12    glClear ( GL_COLOR_BUFFER_BIT );
13
14    // Use the program object
15    glUseProgram ( userData->programObject );
16
17    // Load the vertex data
18    glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
19    glEnableVertexAttribArray ( 0 );
20    glDrawArrays ( GL_TRIANGLES, 0, 3 );
21    eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);

4.1 glClear

清除指定的buffer到预设值。可清除以下四类buffer:

1)GL_COLOR_BUFFER_BIT

2)GL_DEPTH_BUFFER_BIT

3)GL_ACCUM_BUFFER_BIT

4)GL_STENCIL_BUFFER_BIT

预设值通过glClearColor, glClearIndex, glClearDepth, glClearStencil, 和glClearAccum来设置。

1)gClearColor

指定color buffer的清除值,当调用glClear(GL_COLOR_BUFFER_BIT)时才真正用设定的颜色值清除color buffer。参数值的范围为:0~1。

void glClearColor( GLclampf   red, GLclampf   green,  GLclampf   blue,  GLclampf   alpha);

2)glClearIndex

指定color index buffer清除值。void glClearIndex( GLfloat   c);

3)glClearDepth

指定depth buffer的清除值,取值范围为:0~1,默认值为1。

void glClearDepth( GLclampd   depth);

4)glClearStencil

指定stencil buffer清除值的索引,初始值为0。void glClearStencil( GLint   s);

5)glClearAccum

指定accumulation buffer的清除值,初始值为0,取值范围为:-1~1

void glClearAccum( GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha);

4.2 glUseProgram

安装一个program object,并把它作为当前rendering state的一部分。

     1) 当一个可执行程序被安装到vertex processor,下列OpenGL固定功能将被disable:

  • The modelview matrix is not applied to vertex coordinates.
  • The projection matrix is not applied to vertex coordinates.
  • The texture matrices are not applied to texture coordinates.
  • Normals are not transformed to eye coordinates.
  • Normals are not rescaled or normalized.
  • Normalization of GL_AUTO_NORMAL evaluated normals is not performed.
  • Texture coordinates are not generated automatically.
  • Per-vertex lighting is not performed.
  • Color material computations are not performed.
  • Color index lighting is not performed.
  • This list also applies when setting the current raster position.

2) 当一个可执行程序被安装到fragment processor,下列OpenGL固定功能将被disable:

  • Texture environment and texture functions are not applied.
  • Texture application is not applied.
  • Color sum is not applied.
  • Fog is not applied.

4.3 glVertexAttribPointer

定义一个通用顶点属性数组。当渲染时,它指定了通用顶点属性数组从索引index处开始的位置数据格式。其定义如下:

1    void glVertexAttribPointer(
2          GLuint   index,           // 指示将被修改的通用顶点属性的索引
3           GLint   size,             // 指点每个顶点元素个数(1~4)
4          GLenum   type,            // 数组中每个元素的数据类型
5           GLboolean   normalized,   //指示定点数据值是否被归一化(归一化<[-1,1]或[0,1]>:GL_TRUE,直接使用:GL_FALSE)
6          GLsizei   stride,         // 连续顶点属性间的偏移量,如果为0,相邻顶点属性间紧紧相邻
7           const GLvoid *   pointer);//顶点数组
8 //注:其index应该小于#define GL_MAX_VERTEX_ATTRIBS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x8869

4.4 glEnableVertexAttribArray

Enable由索引index指定的通用顶点属性数组。

void glEnableVertexAttribArray( GLuint   index);
      void glDisableVertexAttribArray( GLuint   index);

默认状态下,所有客户端的能力被disabled,包括所有通用顶点属性数组。如果被Enable,通用顶点属性数组中的值将被访问并被用于rendering,通过调用顶点数组命令:glDrawArrays, glDrawElements, glDrawRangeElements, glArrayElement,
glMultiDrawElements, or glMultiDrawArrays.

4.5 glDrawArrays

void glDrawArrays( GLenum   mode, 
                                  GLint   first, 
                                  GLsizei   count);

1) mode:指明render原语,如:GL_POINTS,
GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS, 和 GL_POLYGON。

2) first: 指明Enable数组中起始索引。

3) count: 指明被render的原语个数。

可以预先使用单独的数据定义vertex、normal和color,然后通过一个简单的glDrawArrays构造一系列原语。当调用
glDrawArrays时,它使用每个enable的数组中的count个连续的元素,来构造一系列几何原语,从第first个元素开始。

4.6 eglSwapBuffers

把EGL surface中的color buffer提交到native window进行显示。

EGLBoolean eglSwapBuffers(EGLDisplay display,EGLSurface surface)

5. 协调组织

在前面的描述中,三步曲已经完成了:

1)初始化EGL环境,为绘图做好准备

2)生成Program

3)安装并执行Program

只有这三个关键人物,还不能运行,还需要一个协调组织者。其参考代码如下:

 1 int main(int argc, char** argv)
 2 {
 3     ESContext esContext;
 4     UserData  userData;
 5     int iFrames;
 6     unsigned long iStartTime,iEndTime;
 7     int iDeltaTime;
 8
 9     memset( &esContext, 0, sizeof( ESContext) );
10     esContext.userData = &userData;
11
12     esContext.width = 1280;
13     esContext.height = 720;
14     // Init EGL display, surface and context
15     if(!InitEGL(&esContext))
16     {
17         printf("Init EGL fail\n");
18         return GL_FALSE;
19     }
20     // compile shader, link program
21     if(!CreateProgram(&esContext))
22     {
23         printf("Create Program fail\n");
24         return GL_FALSE;
25     }
26
27
28     iStartTime = GetCurTime();
29     iFrames = 0;
30
31     while(1)
32     {    // render a frame
33          Render(&esContext);
34          iFrames++;
35
36          iEndTime = GetCurTime();
37     iDeltaTime  = iEndTime - iStartTime;
38     if(iDeltaTime >= 5000)
39     {
40               iStartTime = iEndTime;
41         float fFrame = iFrames * 1000.0 / iDeltaTime;
42         iFrames = 0;
43
44         printf("Frame: %f\n", fFrame);
45     }
46     }
47     glDeleteProgram (esContext.userData->programObject);
48     return GL_TRUE;
49 }
时间: 2024-10-05 11:19:33

iOS开发——图形编程OC篇&OpenGL ES2.0编程步骤的相关文章

iOS开发——新特性OC篇&amp;Swift 2.0新特性

Swift 2.0新特性 转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度的WWDC大会如期而至,在大会上Apple发布了Swift 2.0,引入了很多新的特性,以帮助开发者能更快,更简单的构建应用.我在这里也说道说道Swift 2.0中值得大家注意的新特性. guard语句 guard语句和if语句有点类似,都是根据其关键字之后的表达式的布尔值决定下一步执行什么.但与if语句不

iOS开发——使用技术OC篇&amp;项目实战总结之开发技巧

项目实战总结之开发技巧 本文收集了25个关于可以提升程序性能的提示和技巧 1.使用ARC进行内存管理 2.在适当的情况下使用reuseIdentifier 3.尽可能将View设置为不透明(Opaque) 4.避免臃肿的XIBs 5.不要阻塞主线程 6.让图片的大小跟UIImageView一样 7.选择正确的集合 8.使用GZIP压缩 9.重用和延迟加载View 10.缓存.缓存.缓存 11.考虑绘制 12.处理内存警告 13.重用花销很大的对象 14.使用Sprite Sheets 15.避免

ios开发——实用技术篇OC篇&amp;iOS的主要框架

iOS的主要框架         阅读目录 Foundation框架为所有的应用程序提供基本系统服务 UIKit框架提供创建基于触摸用户界面的类 Core Data框架管着理应用程序数据模型 Core Graphics框架帮助你创建图形 Core Animation允许你创建高级的动画和虚拟效果 OpenGL ES 框架提供2D和3D绘图工具 将别的框架添加到工程里 本文是<Sunvey the Major Framworks>一文的翻译 框架是一个目录,这个目录包含了共享库,访问共享库里代码

iOS开发——网络实用技术OC篇&amp;网络爬虫-使用青花瓷抓取网络数据

网络爬虫-使用青花瓷抓取网络数据 由于最近在研究网络爬虫相关技术,刚好看到一篇的的搬了过来! 望谅解..... 写本文的契机主要是前段时间有次用青花瓷抓包有一步忘了,在网上查了半天也没找到写的完整的教程,于是待问题解决后抽时间截了图,自己写一遍封存在博客园中以便以后随时查阅. charles又名青花瓷,在iOS开发中的抓包中具有重要作用.最大的三点用处,一就是拦截别人软件的发送的请求和后端接口,练习开发.二是自己后端返回的response拦截修改后再接收以达到测试临界数据的作用.三写脚本重复拦截

iOS开发——数据持久化OC篇&amp;(三)对象归档

归档 iOS开发UI篇—ios应用数据存储方式(归档)  一.简单说明 在使用plist进行数据存储和读取,只适用于系统自带的一些常用类型才能用,且必须先获取路径相对麻烦: 偏好设置(将所有的东西都保存在同一个文件夹下面,且主要用于存储应用的设置信息) 归档:因为前两者都有一个致命的缺陷,只能存储常用的类型.归档可以实现把自定义的对象存放在文件中. 二.代码示例 1.文件结构 2.代码示例 YYViewController.m文件 1 // 2 // YYViewController.m 3 /

iOS开发——高级技术OC篇&amp;运行时(Runtime)机制

运行时(Runtime)机制 本文将会以笔者个人的小小研究为例总结一下关于iOS开发中运行时的使用和常用方法的介绍,关于跟多运行时相关技术请查看笔者之前写的运行时高级用法及相关语法或者查看响应官方文档. 下面就来看看什么是运行时,我们要怎么在iOS开发中去使用它. 官方介绍: 这里我们主要关注的是最后一种! 下面来看看Runtime的相关总结 #pragma mark 获取属性成员 /********************************************************

iOS开发——高级UI—OC篇&amp;退出键盘

退出键盘 iOS开发中键盘的退出方法用很多中我们应该在合适的地方使用合适的方法才能更好的提高开发的效率和应用的性能 下面给大家介绍几种最常用的键盘退出方法,基本上iOS开发中的键盘退出方法都是这几种中的一种活着几种. 一:textView 1 //通过委托来实现放弃第一响应者 2 #pragma mark - UITextView Delegate Method 3 -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(N

iOS开发——UI精选OC篇&amp;UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍

UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍 一:UIApplication:单例(关于单例后面的文章中会详细介绍,你现在只要知道,单例在应用程序的整个生命周期中只有一个对象). App的启动过程 打开程序之后-> 1:Main函数 2:UIapplicationMain函数 3:初始化UIApplication(创建) 4:设置UIApplication代理和相应的代理属性 5:开启事件循环,监听系统事件 6监测info.p

iOS 开发——版本适配OC篇&amp;项目开发之系统适配问题(关于后台)

项目开发之系统适配问题 关于后台 在之前iOS 开发中,我们精彩遇到关于app适配问题,有屏幕适配,系统适配,但是由于苹果新设备(iphone 6/6p)技新术(sizeClass)的推出在屏幕适配上变的非常简单,而且之前关于app在系统适配上还是比较多的,可能是由于ios7的大改革,后面字啊iOS7盒iOS8上面的api并没有太大的差别,所以关于系统适配,我们并没有考虑太多. 但是,作为一个合格的开发者,不管是实际项目开发中,还是平时我们都要注意系统的视频,毕竟ios9又出来了,虽然常用api