1. 程式人生 > >OpenGL ES2 0程式設計三步曲

OpenGL ES2 0程式設計三步曲

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

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.0f0.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;}



 

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述