OpenGL ES2.0编程步骤

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

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

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

 typedef struct _escontext
 {
    void*       userData;                    // Put your user data here...
    GLint       width;                          // Window width
    GLint       height;                         // Window height
    EGLNativeWindowType  hWnd;  // Window handle
    EGLDisplay  eglDisplay;             // EGL display
    EGLContext  eglContext;            // EGL context
    EGLSurface  eglSurface;            // EGL surface

    // Callbacks
    void (ESCALLBACK *drawFunc) ( struct _escontext * );
    void (ESCALLBACK *keyFunc) ( struct _escontext *, unsigned char, int, int );
    void (ESCALLBACK *updateFunc) ( struct _escontext *, float deltaTime );
 }ESContext;
 typedef struct
 {
    // Handle to a program object
    GLuint programObject;

    // Atrribute Location
    GLint positionLoc;
    GLint textureLoc;

    // Uniform location
    GLint matrixModeLoc;
    GLint matrixViewLoc;
    GLint matrixPerspectiveLoc;

    // Sampler location
    GLint samplerLoc;

    // texture
    GLuint texture;
 } UserData;

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

 int InitEGL(ESContext * esContext)
 {
      NativeWindowType eglWindow = NULL;

      EGLDisplay display;
      EGLContext context;
      EGLSurface surface;

      EGLConfig configs[];
      EGLBoolean eRetStatus;
      EGLint majorVer, minorVer;
      EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, , EGL_NONE};

      EGLint numConfigs;
      EGLint cfg_attribs[] = {EGL_BUFFER_SIZE,    EGL_DONT_CARE,
                              EGL_DEPTH_SIZE,     ,
                              EGL_RED_SIZE,       ,
                              EGL_GREEN_SIZE,     ,
                              EGL_BLUE_SIZE,      ,
                              EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                              EGL_NONE};

      // Get default display connection
      display = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
      if ( display == EGL_NO_DISPLAY )
      {
           return EGL_FALSE;
      }

      // Initialize EGL display connection
      eRetStatus = eglInitialize(display, &majorVer, &minorVer);
      if( eRetStatus != EGL_TRUE )
      {
           return EGL_FALSE;
      }

      //Get a list of all EGL frame buffer configurations for a display
      eRetStatus = eglGetConfigs (display, configs, , &numConfigs);
      if( eRetStatus != EGL_TRUE )
      {
           return EGL_FALSE;
      }

      // Get a list of EGL frame buffer configurations that match specified attributes
      eRetStatus = eglChooseConfig (display, cfg_attribs, configs, , &numConfigs);
      if( eRetStatus != EGL_TRUE  || !numConfigs)
      {
           return EGL_FALSE;
      }

      // Create a new EGL window surface
      surface = eglCreateWindowSurface(display, configs[], eglWindow, NULL);
      if (surface == EGL_NO_SURFACE)
      {
           return EGL_FALSE;
      }

      // Set the current rendering API (EGL_OPENGL_API, EGL_OPENGL_ES_API,EGL_OPENVG_API)
      eRetStatus = eglBindAPI(EGL_OPENGL_ES_API);
      if (eRetStatus != EGL_TRUE)
      {
           return EGL_FALSE;
      }

      // Create a new EGL rendering context
      context = eglCreateContext (display, configs[], EGL_NO_CONTEXT, context_attribs);
      if (context == EGL_NO_CONTEXT)
      {
           return EGL_FALSE;
      }

      // Attach an EGL rendering context to EGL surfaces
      eRetStatus = eglMakeCurrent (display, surface, surface, context);
      if( eRetStatus != EGL_TRUE )
      {
           return EGL_FALSE;
      }
      //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.
      eglSwapInterval(display,);

      // Return the context elements
      esContext->eglDisplay = display;
      esContext->eglSurface = surface;
      esContext->eglContext = context;

      return EGL_TRUE;
 }

3. 生成Program (第二步曲)

3.1 LoadShader

LoadShader主要实现以下功能:

1) 创建Shader对象

2) 装载Shader源码

3) 编译Shader

其实现参考代码如下:

 /* type specifies the Shader type: GL_VERTEX_SHADER or GL_FRAGMENT_SHADER */
 GLuint LoadShader ( GLenum type, const char *shaderSrc )
 {
    GLuint shader;
    GLint compiled;

    // Create an empty shader object, which maintain the source code strings that define a shader
    shader = glCreateShader ( type );

     )
        ;

    // Replaces the source code in a shader object
    glShaderSource ( shader, , &shaderSrc, NULL );

    // Compile the shader object
    glCompileShader ( shader );

    // Check the shader object compile status
    glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );

    if ( !compiled )
    {
       GLint infoLen = ;

       glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );

        )
       {
          char* infoLog = malloc (sizeof(char) * infoLen );

          glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
          esLogMessage ( "Error compiling shader:\n%s\n", infoLog );            

          free ( infoLog );
       }

       glDeleteShader ( shader );
       ;
    }

    return shader;
 }

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

其参考代码如下:

 GLuint LoadProgram ( const char *vShaderStr, const char *fShaderStr )
 {
    GLuint vertexShader;
    GLuint fragmentShader;
    GLuint programObject;
    GLint linked;

    // Load the vertex/fragment shaders
    vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
    fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );

    // Create the program object
    programObject = glCreateProgram ( );
     )
       ;

    // Attaches a shader object to a program object
    glAttachShader ( programObject, vertexShader );
    glAttachShader ( programObject, fragmentShader );
    // Bind vPosition to attribute 0  
    glBindAttribLocation ( programObject, , "vPosition" );
    // Link the program object
    glLinkProgram ( programObject );

    // Check the link status
    glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );

    if ( !linked )
    {
       GLint infoLen = ;

       glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );

        )
       {
          char* infoLog = malloc (sizeof(char) * infoLen );

          glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
          esLogMessage ( "Error linking program:\n%s\n", infoLog );            

          free ( infoLog );
       }

       glDeleteProgram ( programObject );
       return GL_FALSE;
    }

    // Free no longer needed shader resources
    glDeleteShader ( vertexShader );
    glDeleteShader ( fragmentShader );

    return programObject;
 }

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的链接,现在还缺少真正供进行编译和链接的源码,其参考代码如下:

 int CreateProgram(ESContext * esContext)
 {
      GLuint programObject;

      GLbyte vShaderStr[] =
       "attribute vec4 vPosition;    \n"
       "void main()                  \n"
       "{                            \n"
       "   gl_Position = vPosition;  \n"
       "}                            \n";

      GLbyte fShaderStr[] =
       "precision mediump float;\n"\
       "void main()                                  \n"
       "{                                            \n"
       "  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
       "}                                                    \n";

     // Create user data
     esContext->userData = malloc(sizeof(UserData));
     UserData *userData = esContext->userData;

     // Load the shaders and get a linked program object
     programObject = LoadProgram ( (const char*)vShaderStr, (const char*)fShaderStr );
     )
     {
     return GL_FALSE;
     }

     // Store the program object
     userData->programObject = programObject;

     // Get the attribute locations
     userData->positionLoc = glGetAttribLocation ( g_programObject, "v_position" );
     glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
     ;
 }

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

 void Render ( ESContext *esContext )
 {
    UserData *userData = esContext->userData;
    GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
                            -0.5f, -0.5f, 0.0f,
                             0.5f, -0.5f, 0.0f };

    // Set the viewport
    glViewport ( , , esContext->width, esContext->height );

    // Clear the color buffer
    glClear ( GL_COLOR_BUFFER_BIT );

    // Use the program object
    glUseProgram ( userData->programObject );

    // Load the vertex data
    glVertexAttribPointer ( , , GL_FLOAT, GL_FALSE, , vVertices );
    glEnableVertexAttribArray (  );
    glDrawArrays ( GL_TRIANGLES, ,  );
    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处开始的位置数据格式。其定义如下:

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

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

 int main(int argc, char** argv)
 {
     ESContext esContext;
     UserData  userData;
     int iFrames;
     unsigned long iStartTime,iEndTime;
     int iDeltaTime;

     memset( &esContext, , sizeof( ESContext) );
     esContext.userData = &userData;

     esContext.width = ;
     esContext.height = ;
     // Init EGL display, surface and context
     if(!InitEGL(&esContext))
     {
         printf("Init EGL fail\n");
         return GL_FALSE;
     }
     // compile shader, link program
     if(!CreateProgram(&esContext))
     {
         printf("Create Program fail\n");
         return GL_FALSE;
     }

     iStartTime = GetCurTime();
     iFrames = ;

     )
     {    // render a frame
          Render(&esContext);
          iFrames++;

          iEndTime = GetCurTime();
     iDeltaTime  = iEndTime - iStartTime;
     )
     {
               iStartTime = iEndTime;
         float fFrame = iFrames * 1000.0 / iDeltaTime;
         iFrames = ;

         printf("Frame: %f\n", fFrame);
     }
     }
     glDeleteProgram (esContext.userData->programObject);
     return GL_TRUE;
 }
 

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

  1. iOS开发——新特性OC篇&Swift 2.0新特性

    Swift 2.0新特性     转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度 ...

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

    iOS的主要框架         阅读目录 Foundation框架为所有的应用程序提供基本系统服务 UIKit框架提供创建基于触摸用户界面的类 Core Data框架管着理应用程序数据模型 Core ...

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

    网络爬虫-使用青花瓷抓取网络数据 由于最近在研究网络爬虫相关技术,刚好看到一篇的的搬了过来! 望谅解..... 写本文的契机主要是前段时间有次用青花瓷抓包有一步忘了,在网上查了半天也没找到写的完整的教 ...

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

    运行时(Runtime)机制 本文将会以笔者个人的小小研究为例总结一下关于iOS开发中运行时的使用和常用方法的介绍,关于跟多运行时相关技术请查看笔者之前写的运行时高级用法及相关语法或者查看响应官方文档 ...

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

    UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍 一:UIApplication:单例(关于单例后面的文章中会详细介绍,你现在只要知道 ...

  6. iOS开发——运行时OC篇&使用运行时获取系统的属性:使用自己的手势修改系统自带的手势

    使用运行时获取系统的属性:使用自己的手势修改系统自带的手势 有的时候我需要实现一个功能,但是没有想到很好的方法或者想到了方法只是那个方法实现起来太麻烦,一或者确实为了装逼,我们就会想到iOS开发中最牛 ...

  7. iOS开发——网络实用技术OC篇&网络爬虫-使用java语言抓取网络数据

    网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一 ...

  8. iOS开发——高级UI—OC篇&退出键盘

    退出键盘 iOS开发中键盘的退出方法用很多中我们应该在合适的地方使用合适的方法才能更好的提高开发的效率和应用的性能 下面给大家介绍几种最常用的键盘退出方法,基本上iOS开发中的键盘退出方法都是这几种中 ...

  9. iOS开发——技术精华Swift篇&Swift 2.0和Objective-C2.0混编之第三方框架的使用

    swift 语言是苹果公司在2014年的WWDC大会上发布的全新的编程语言.Swift语言继承了C语言以及Objective-C的特性,且克服了C语言的兼容性问题.Swift语言采用安全编程模式,且引 ...

随机推荐

  1. C#中的值类型(value type)与引用类型(reference type)的区别

    ylbtech- .NET-Basic:C#中的值类型与引用类型的区别 C#中的值类型(value type)与引用类型(reference type)的区别 1.A,相关概念返回顶部     C#中 ...

  2. 同行评审 Peer Review

    周五的课上,章老师给我们上了一节关于同行评审(Peer Review)的课程,让我了解了以前并不熟悉的这一过程.课上我们就姚思丹同学项目组做的项目,分组进行了审查. 首先介绍一下同行评审(Peer R ...

  3. 试验Windows Embedded Standard 7 Service Pack 1 Evaluation Edition

    =========================================== 是否支持再使用 RT 7 Lite 精简 ? ================================= ...

  4. ASM中的别名

    在ASM中的别名,是为了方便管理. 在ASM中创建别名,一种是在RDBMS中创建,另外一种是在ASM中创建,区别就是在ASM中创建的别名,在RDBMS中是不可见的. 在RDBMS中创建别名: SQL& ...

  5. nodejs写的一个网页爬虫例子(坏链率)

    因为工作需要,用nodejs写了个简单的爬虫例子,之前也没用过nodejs,连搭环境加写大概用了5天左右,so...要多简陋有多简陋,放这里给以后的自己看~~ 整体需求是:给一个有效的URL地址,返回 ...

  6. PHP实现分页:文本分页和数字分页

    来源:http://www.ido321.com/1086.html 最近,在项目中要用到分页.分页功能是经常使用的一个功能,所以,对其以函数形式进行了封装. // 分页分装 /** * $pageT ...

  7. CentOS6 搭建git

    rpm -qa | grep zlib-devel  查看是否安装过 ----------------------------------------------------------------- ...

  8. 【成都GamEver游戏公司诚邀服务器伙伴】【7~15k一年4次项目奖金】

    关于我们 我们厌倦了朝九晚五,一眼看到头的人生我们厌倦了耗费自己青春做的都是没有感情的项目平均从业经验5年以上行业顶尖美术和金牌制作人,资深欧美制作经验立志做中国的suppercell,公司小而美 我 ...

  9. “大数据讲师”、“Hadoop讲师”、“Spark讲师”、“云计算讲师”、“Android讲师”

    王家林简介 Spark亚太研究院院长和首席专家,中国目前唯一的移动互联网和云计算大数据集大成者. 在Spark.Hadoop.Android等方面有丰富的源码.实务和性能优化经验.彻底研究了Spark ...

  10. NodeJs 开源

    iwebpp.io - 运行P2P Node.js web 服务,穿透防火墙,NAT https://github.com/InstantWebP2P/iwebpp.io pm 是一个轻量级的Node ...