OpenGL ES2.0编程三步曲

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[2];
     EGLBoolean eRetStatus;
     EGLint majorVer, minorVer;
     EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};

     EGLint numConfigs;
     EGLint cfg_attribs[] = {EGL_BUFFER_SIZE,    EGL_DONT_CARE,
                             EGL_DEPTH_SIZE,     16,
                             EGL_RED_SIZE,       5,
                             EGL_GREEN_SIZE,     6,
                             EGL_BLUE_SIZE,      5,
                             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, 2, &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, 2, &numConfigs);
     if( eRetStatus != EGL_TRUE  || !numConfigs)
     {
          return EGL_FALSE;
     }

     // Create a new EGL window surface
     surface = eglCreateWindowSurface(display, configs[0], 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[0], 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,0);

     // 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 );

   if ( shader == 0 )
   	return 0;

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

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

   if ( !compiled ) 
   {
      GLint infoLen = 0;

      glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
      
      if ( infoLen > 1 )
      {
         char* infoLog = malloc (sizeof(char) * infoLen );

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

      glDeleteShader ( shader );
      return 0;
   }

   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 ( );
   if ( programObject == 0 )
      return 0;

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

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

   if ( !linked ) 
   {
      GLint infoLen = 0;

      glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
      
      if ( infoLen > 1 )
      {
         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 );
    if(programObject == 0)
    {
	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 );
    return 0;
}

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 ( 0, 0, 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 ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
   glEnableVertexAttribArray ( 0 );
   glDrawArrays ( GL_TRIANGLES, 0, 3 );
   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               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, 0, sizeof( ESContext) );
    esContext.userData = &userData;

    esContext.width = 1280;
    esContext.height = 720;
    // 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 = 0;

    while(1)
    {    // render a frame
         Render(&esContext);
         iFrames++;
        
         iEndTime = GetCurTime();
	iDeltaTime  = iEndTime - iStartTime;
	if(iDeltaTime >= 5000)
	{
          	iStartTime = iEndTime;
		float fFrame = iFrames * 1000.0 / iDeltaTime;
		iFrames = 0;

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



 

  • 0
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 《OpenGL ES 2.0编程指南》是一本介绍OpenGL ES 2.0编程技术和方法的指南。OpenGL ESOpenGL for Embedded Systems)是一套专为嵌入式系统和移动设备设计的2D和3D图形API,而OpenGL ES 2.0是其中的版本之一。 这本指南首先介绍了OpenGL ES 2.0编程的基础知识,包括OpenGL ES的特性和架构,以及基本的绘制流程。然后,它详细介绍了OpenGL ES 2.0的着色器编程,包括顶点着色器和片段着色器。着色器编程OpenGL ES 2.0的核心,通过编写和使用着色器代码,开发者可以灵活地控制和定制图形渲染的各个环节。 此外,该指南还介绍了OpenGL ES 2.0的纹理映射、混合、剪裁和光照等高级技术。纹理映射可以让开发者在场景中添加细节和图案,混合可以实现透明效果,剪裁可以限制绘制的区域,光照可以增强场景的真实感。 《OpenGL ES 2.0编程指南》还提供了丰富的实例代码和实践案例,让读者能够通过实际操作深入理解OpenGL ES 2.0编程方法和技巧。通过学习和掌握本书的内容,读者可以成为一名优秀的OpenGL ES 2.0开发者,能够开发出高性能、高质量的嵌入式图形应用程序。 总之,《OpenGL ES 2.0编程指南》是一本权威、全面且具有实践性的指南,对想要学习和应用OpenGL ES 2.0的开发者来说是一本非常有价值的参考书。 ### 回答2: 《OpenGLES2.0编程指南》是一本介绍OpenGL ES 2.0编程的指南书籍。OpenGL ES是一种针对移动设备和嵌入式系统的图形库,而OpenGL ES 2.0是其最新版本,提供了强大的图形渲染功能和灵活的编程接口。 这本书以深入浅出的方式介绍了OpenGL ES 2.0的基本概念、渲染管线、顶点和片元着色器、纹理映射、渲染缓冲区和帧缓冲区等核心知识。读者可以通过学习本书,了解到如何利用OpenGL ES 2.0编写高性能的图形应用程序。 在《OpenGLES2.0编程指南》中,作者还会通过大量的示例代码来演示如何使用OpenGL ES 2.0进行图形渲染。这些示例代码会涉及到常用的图形渲染技术,如图元绘制、光照、投影变换、深度测试等。读者可以通过对这些示例代码的学习和分析,更好地理解OpenGL ES 2.0编程思想和技术要点。 此外,本书还介绍了一些常见的图形效果和优化技巧,如阴影、反射和抗锯齿等。这些内容对于那些希望提升图形应用程序性能和效果的开发者来说十分有用。 总的来说,《OpenGLES2.0编程指南》是一本全面而深入的OpenGL ES 2.0编程教材,适合那些想要学习OpenGL ES 2.0编程或者提升自己OpenGL ES 2.0编程技能的开发者阅读。通过学习本书,读者可以掌握OpenGL ES 2.0的基本知识和相关的编程技术,进一步提高自己在图形应用开发领域的水平。 ### 回答3: 《OpenGL ES 2.0编程指南》是一本深入解析OpenGL ES 2.0编程的指南。OpenGL ESOpenGL for Embedded Systems)是为嵌入式设备和移动设备设计的精简版OpenGL。这本指南主要面向对OpenGL ES 2.0编程感兴趣的开发人员。 本书首先介绍了OpenGL ES 2.0的基本概念和工作原理。接着详细讲解了OpenGL ES 2.0的渲染管线、着色器语言以及顶点和片元着色器的编程。书中还提供了大量的示例代码和实践案例,帮助读者更好地理解各种概念和技术,并应用于实际项目中。 《OpenGL ES 2.0编程指南》还涵盖了纹理映射、深度缓冲、帧缓冲和多重渲染目标等高级主题。读者可以学习到如何使用这些高级功能实现更加复杂的图形效果。此外,书中还介绍了一些优化技巧和调试方法,帮助开发人员提高应用性能并排除错误。 这本指南对于初学者来说可能会有一些挑战,因为OpenGL ES 2.0编程相对复杂。但对于有一定OpenGL基础的开发人员来说,它是一本非常有价值的参考书。作为一本权威的OpenGL ES 2.0编程指南,它提供了丰富的知识和实践经验,可以帮助读者掌握这一领域的核心技术和开发流程。 综上所述,《OpenGL ES 2.0编程指南》是一本深入介绍和解析OpenGL ES 2.0编程的权威指南。无论是初学者还是有经验的开发人员,都可以通过阅读这本书来学习和应用OpenGL ES 2.0编程技术。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值