SimpleGL example: Difference between revisions

From Maemo Wiki
Jump to navigationJump to search
imported>endboss
added screen shot
Change only_if_exists to False, then the atom is created if it does not exist to avoid return invalid atom.
 
(8 intermediate revisions by 4 users not shown)
Line 1: Line 1:
This is a simple program demonstrating how to use openGL ES 2.0. It will output this animated spiral, which can be moved around on the screen:
This is a simple program demonstrating how to use [[OpenGL-ES#OpenGL_variants|OpenGL ES 2.0]]. It will output this animated spiral, which can be moved around on the screen:


[[Image:Egl-example_output.png]]
[[Image:Egl-example_output.png]]


<source lang="cpp">
/* Created by exoticorn ( http://talk.maemo.org/showthread.php?t=37356 )
* edited and commented by André Bergner [endboss]
*
* libraries needed:  libx11-dev, libgles2-dev
*
* compile with:  g++  -lX11 -lEGL -lGLESv2  egl-example.cpp
*/


  /* Created by exoticorn ( http://talk.maemo.org/showthread.php?t=37356 )
#include <iostream>
  * edited and commented by André Bergner [endboss]
#include  <cstdlib>
  *
#include  <cstring>
  * librariries needed:  libx11-dev, libgles2-dev
using namespace std;
  *
 
  * compile with:  g++  -lX11 -lEGL -lGLESv2  egl-example.cpp
#include  <cmath>
  */
#include <sys/time.h>
 
#include  <iostream>
#include  <X11/Xlib.h>
  using namespace std;
#include  <X11/Xatom.h>
#include  <X11/Xutil.h>
#include  <cmath>
 
#include  <sys/time.h>
#include  <GLES2/gl2.h>
#include  <EGL/egl.h>
#include  <X11/Xlib.h>
 
#include  <X11/Xatom.h>
 
 
#include  <GLES2/gl2.h>
const char vertex_src [] =
#include  <EGL/egl.h>
"                                        \
  attribute vec4        position;      \
  varying mediump vec2  pos;            \
  uniform vec4          offset;        \
const char vertex_src [] =
                                        \
"                                        \
  void main()                          \
    attribute vec4        position;      \
  {                                    \
    varying mediump vec2  pos;            \
      gl_Position = position + offset;  \
    uniform vec4          offset;        \
      pos = position.xy;                \
                                          \
  }                                    \
    void main()                          \
";
    {                                    \
 
      gl_Position = position + offset;  \
 
      pos = position.xy;                \
const char fragment_src [] =
    }                                    \
"                                                      \
";
  varying mediump vec2    pos;                        \
  uniform mediump float  phase;                      \
                                                      \
const char fragment_src [] =
  void  main()                                        \
"                                                      \
  {                                                  \
    varying mediump vec2    pos;                        \
      gl_FragColor  =  vec4( 1., 0.9, 0.7, 1.0 ) *    \
    uniform mediump float  phase;                      \
        cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y)  \
                                                        \
            + atan(pos.y,pos.x) - phase );            \
    void  main()                                        \
  }                                                  \
    {                                                  \
";
      gl_FragColor  =  vec4( 1., 0.9, 0.7, 1.0 ) *    \
//  some more formulas to play with...
        cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y)  \
//      cos( 20.*(pos.x*pos.x + pos.y*pos.y) - phase );
              + atan(pos.y,pos.x) - phase );            \
//      cos( 20.*sqrt(pos.x*pos.x + pos.y*pos.y) + atan(pos.y,pos.x) - phase );
    }                                                  \
//      cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y - 1.8*pos.x*pos.y*pos.y)
";
//            + atan(pos.y,pos.x) - phase );
//  some more formulas to play with...
 
//      cos( 20.*(pos.x*pos.x + pos.y*pos.y) - phase );
 
//      cos( 20.*sqrt(pos.x*pos.x + pos.y*pos.y) + atan(pos.y,pos.x) - phase );
void
//      cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y - 1.8*pos.x*pos.y*pos.y)
print_shader_info_log (
//            + atan(pos.y,pos.x) - phase );
  GLuint  shader      // handle to the shader
)
{
void
  GLint  length;
print_shader_info_log (
 
    GLuint  shader      // handle to the shader
  glGetShaderiv ( shader , GL_INFO_LOG_LENGTH , &length );
)
 
{
  if ( length ) {
    GLint  length;
      char* buffer  =  new char [ length ];
      glGetShaderInfoLog ( shader , length , NULL , buffer );
    glGetShaderiv ( shader , GL_INFO_LOG_LENGTH , &length );
      cout << "shader info: " <<  buffer << flush;
      delete [] buffer;
    if ( length ) {
 
      char* buffer  =  new char [ length ];
      GLint success;
      glGetShaderInfoLog ( shader , length , NULL , buffer );
      glGetShaderiv( shader, GL_COMPILE_STATUS, &success );
      cout << "shader info: " <<  buffer << flush;
      if ( success != GL_TRUE )  exit ( 1 );
      delete [] buffer;
  }
}
      GLint success;
 
      glGetShaderiv( shader, GL_COMPILE_STATUS, &success );
 
      if ( success != GL_TRUE )  exit ( 1 );
GLuint
    }
load_shader (
}
  const char  *shader_source,
  GLenum      type
)
GLuint
{
load_shader (
  GLuint  shader = glCreateShader( type );
    const char  *shader_source,
 
    GLenum      type
  glShaderSource  ( shader , 1 , &shader_source , NULL );
)
  glCompileShader ( shader );
{
 
    GLuint  shader = glCreateShader( type );
  print_shader_info_log ( shader );
 
    glShaderSource  ( shader , 1 , &shader_source , NULL );
  return shader;
    glCompileShader ( shader );
}
 
    print_shader_info_log ( shader );
 
Display    *x_display;
    return shader;
Window      win;
}
EGLDisplay  egl_display;
EGLContext  egl_context;
EGLSurface egl_surface;
Display    *x_display;
 
Window      win;
GLfloat
EGLDisplay  egl_display;
  norm_x    =  0.0,
EGLContext  egl_context;
  norm_y    =  0.0,
   
  offset_x  =  0.0,
GLfloat
  offset_y  =  0.0,
    norm_x    =  0.0,
  p1_pos_x  =  0.0,
    norm_y    =  0.0,
  p1_pos_y  =  0.0;
    offset_x  =  0.0,
 
    offset_y  =  0.0,
GLint
    p1_pos_x  =  0.0,
  phase_loc,
    p1_pos_y  =  0.0;
  offset_loc,
  position_loc;
GLint
 
    phase_loc,
 
    offset_loc,
bool        update_pos = false;
    position_loc;
 
const float vertexArray[] = {
  0.0,  0.5,  0.0,
EGLSurface  egl_surface;
  -0.5,  0.0,  0.0,
bool        update_pos = false;
  0.0, -0.5,  0.0,
  0.5,  0.0,  0.0,
const float vertexArray[] = {
  0.0,  0.5,  0.0  
    0.0,  0.5,  0.0,
};
  -0.5,  0.0,  0.0,
 
    0.0, -0.5,  0.0,
 
    0.5,  0.0,  0.0,
void  render()
    0.0,  0.5,  0.0  
{
};
  static float  phase = 0;
  static int    donesetup = 0;
 
void  render()
  static XWindowAttributes gwa;
{
 
    static float  phase = 0;
  //// draw
    static int    donesetup = 0;
 
  if ( !donesetup ) {
    static XWindowAttributes gwa;
      XWindowAttributes  gwa;
      XGetWindowAttributes ( x_display , win , &gwa );
    //// draw
      glViewport ( 0 , 0 , gwa.width , gwa.height );
      glClearColor ( 0.08 , 0.06 , 0.07 , 1.);    // background color
    if ( !donesetup ) {
      donesetup = 1;
      XWindowAttributes  gwa;
  }
      XGetWindowAttributes ( x_display , win , &gwa );
  glClear ( GL_COLOR_BUFFER_BIT );
      glViewport ( 0 , 0 , gwa.width , gwa.height );
 
      glClearColor ( 0.08 , 0.06 , 0.07 , 1.);    // background color
  glUniform1f ( phase_loc , phase );  // write the value of phase to the shaders phase
      donesetup = 1;
  phase  =  fmodf ( phase + 0.5f , 2.f * 3.141f );    // and update the local variable
    }
 
    glClear ( GL_COLOR_BUFFER_BIT );
  if ( update_pos ) {  // if the position of the texture has changed due to user action
      GLfloat old_offset_x  =  offset_x;
    glUniform1f ( phase_loc , phase );  // write the value of phase to the shaders phase
      GLfloat old_offset_y  =  offset_y;
    phase  =  fmodf ( phase + 0.5f , 2.f * 3.141f );    // and update the local variable
 
      offset_x  =  norm_x - p1_pos_x;
    if ( update_pos ) {  // if the position of the texture has changed due to user action
      offset_y  =  norm_y - p1_pos_y;
      GLfloat old_offset_x  =  offset_x;
 
      GLfloat old_offset_y  =  offset_y;
      p1_pos_x  =  norm_x;
      p1_pos_y  =  norm_y;
      offset_x  =  norm_x - p1_pos_x;
 
      offset_y  =  norm_y - p1_pos_y;
      offset_x  +=  old_offset_x;
      offset_y  +=  old_offset_y;
      p1_pos_x  =  norm_x;
 
      p1_pos_y  =  norm_y;
      update_pos = false;
  }
      offset_x  +=  old_offset_x;
 
      offset_y  +=  old_offset_y;
  glUniform4f ( offset_loc  ,  offset_x , offset_y , 0.0 , 0.0 );
 
      update_pos = false;
  glVertexAttribPointer ( position_loc, 3, GL_FLOAT, false, 0, vertexArray );
    }
  glEnableVertexAttribArray ( position_loc );
  glDrawArrays ( GL_TRIANGLE_STRIP, 0, 5 );
    glUniform4f ( offset_loc  ,  offset_x , offset_y , 0.0 , 0.0 );
 
  eglSwapBuffers ( egl_display, egl_surface );  // get the rendered buffer to the screen
    glVertexAttribPointer ( position_loc, 3, GL_FLOAT, false, 0, vertexArray );
}
    glEnableVertexAttribArray ( position_loc );
 
    glDrawArrays ( GL_TRIANGLE_STRIP, 0, 5 );
 
////////////////////////////////////////////////////////////////////////////////////////////
    eglSwapBuffers ( egl_display, egl_surface );  // get the rendered buffer to the screen
 
}
 
int  main()
{
////////////////////////////////////////////////////////////////////////////////////////////
  ///////  the X11 part  //////////////////////////////////////////////////////////////////
  // in the first part the program opens a connection to the X11 window manager
  //
int  main()
 
{
  x_display = XOpenDisplay ( NULL );  // open the standard display (the primary screen)
    ///////  the X11 part  //////////////////////////////////////////////////////////////////
  if ( x_display == NULL ) {
    // in the first part the program opens a connection to the X11 window manager
      cerr << "cannot connect to X server" << endl;
    //
      return 1;
  }
    x_display = XOpenDisplay ( NULL );  // open the standard display (the primary screen)
 
    if ( x_display == NULL ) {
  Window root  =  DefaultRootWindow( x_display );  // get the root window (usually the whole screen)
      cerr << "cannot connect to X server" << endl;
 
      return 1;
  XSetWindowAttributes  swa;
    }
  swa.event_mask  =  ExposureMask | PointerMotionMask | KeyPressMask;
 
    Window root  =  DefaultRootWindow( x_display );  // get the root window (usually the whole screen)
  win  =  XCreateWindow (   // create a window with the provided parameters
              x_display, root,
    XSetWindowAttributes  swa;
              0, 0, 800, 480,  0,
    swa.event_mask  =  ExposureMask | PointerMotionMask;
              CopyFromParent, InputOutput,
              CopyFromParent, CWEventMask,
    win  =  XCreateWindow (         // create a window with the provided parameters
              &swa );
              x_display, root,
 
              0, 0, 800, 480,  0,
  XSetWindowAttributes  xattr;
              CopyFromParent, InputOutput,
  Atom  atom;
              CopyFromParent, CWEventMask,
  int  one = 1;
              &swa );
 
  xattr.override_redirect = False;
    XSetWindowAttributes  xattr;
  XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr );
    Atom  atom;
 
    int  one = 1;
  atom = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", True );
  XChangeProperty (
    xattr.override_redirect = False;
      x_display, win,
    XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr );
      XInternAtom ( x_display, "_NET_WM_STATE", True ),
      XA_ATOM,  32,  PropModeReplace,
    atom = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", True );
      (unsigned char*) &atom,  1 );
    XChangeProperty (
 
      x_display, win,
  XChangeProperty (
      XInternAtom ( x_display, "_NET_WM_STATE", True ),
      x_display, win,
      XA_ATOM,  32,  PropModeReplace,
      XInternAtom ( x_display, "_HILDON_NON_COMPOSITED_WINDOW", False ),
      (unsigned char*) &atom,  1 );
      XA_INTEGER,  32,  PropModeReplace,
      (unsigned char*) &one,  1);
    XChangeProperty (
 
      x_display, win,
  XWMHints hints;
      XInternAtom ( x_display, "_HILDON_NON_COMPOSITED_WINDOW", True ),
  hints.input = True;
      XA_INTEGER,  32,  PropModeReplace,
  hints.flags = InputHint;
      (unsigned char*) &one,  1);
  XSetWMHints(x_display, win, &hints);
 
    XMapWindow ( x_display , win );            // make the window visible on the screen
  XMapWindow ( x_display , win );            // make the window visible on the screen
    XStoreName ( x_display , win , "GL test" ); // give the window a name
  XStoreName ( x_display , win , "GL test" ); // give the window a name
 
    //// get identifiers for the provided atom name strings
  //// get identifiers for the provided atom name strings
    Atom wm_state  = XInternAtom ( x_display, "_NET_WM_STATE", False );
  Atom wm_state  = XInternAtom ( x_display, "_NET_WM_STATE", False );
    Atom fullscreen = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", False );
  Atom fullscreen = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", False );
 
    XEvent xev;
  XEvent xev;
    memset ( &xev, 0, sizeof(xev) );
  memset ( &xev, 0, sizeof(xev) );
 
    xev.type                = ClientMessage;
  xev.type                = ClientMessage;
    xev.xclient.window      = win;
  xev.xclient.window      = win;
    xev.xclient.message_type = wm_state;
  xev.xclient.message_type = wm_state;
    xev.xclient.format      = 32;
  xev.xclient.format      = 32;
    xev.xclient.data.l[0]    = 1;
  xev.xclient.data.l[0]    = 1;
    xev.xclient.data.l[1]    = fullscreen;
  xev.xclient.data.l[1]    = fullscreen;
    XSendEvent (                // send an event mask to the X-server
  XSendEvent (                // send an event mask to the X-server
      x_display,
      x_display,
      DefaultRootWindow ( x_display ),
      DefaultRootWindow ( x_display ),
      False,
      False,
      SubstructureNotifyMask,
      SubstructureNotifyMask,
      &xev );
      &xev );
 
 
    ///////  the egl part  //////////////////////////////////////////////////////////////////
  ///////  the egl part  //////////////////////////////////////////////////////////////////
    //  egl provides an interface to connect the graphics related functionality of openGL ES
  //  egl provides an interface to connect the graphics related functionality of openGL ES
    //  with the windowing interface and functionality of the native operation system (X11
  //  with the windowing interface and functionality of the native operation system (X11
    //  in our case.
  //  in our case.
 
    egl_display  =  eglGetDisplay( (EGLNativeDisplayType) x_display );
  egl_display  =  eglGetDisplay( (EGLNativeDisplayType) x_display );
    if ( egl_display == EGL_NO_DISPLAY ) {
  if ( egl_display == EGL_NO_DISPLAY ) {
      cerr << "Got no EGL display." << endl;
      cerr << "Got no EGL display." << endl;
      return 1;
      return 1;
    }
  }
 
    if ( !eglInitialize( egl_display, NULL, NULL ) ) {
  if ( !eglInitialize( egl_display, NULL, NULL ) ) {
      cerr << "Unable to initialize EGL" << endl;
      cerr << "Unable to initialize EGL" << endl;
      return 1;
      return 1;
    }
  }
 
    EGLint attr[] = {      // some attributes to set up our egl-interface
  EGLint attr[] = {      // some attributes to set up our egl-interface
      EGL_BUFFER_SIZE, 16,
      EGL_BUFFER_SIZE, 16,
      EGL_RENDERABLE_TYPE,
      EGL_RENDERABLE_TYPE,
      EGL_OPENGL_ES2_BIT,
      EGL_OPENGL_ES2_BIT,
      EGL_NONE
      EGL_NONE
    };
  };
 
    EGLConfig  ecfg;
  EGLConfig  ecfg;
    EGLint    num_config;
  EGLint    num_config;
    if ( !eglChooseConfig( egl_display, attr, &ecfg, 1, &num_config ) ) {
  if ( !eglChooseConfig( egl_display, attr, &ecfg, 1, &num_config ) ) {
      cerr << "Failed to choose config (eglError: " << eglGetError() << ")" << endl;
      cerr << "Failed to choose config (eglError: " << eglGetError() << ")" << endl;
      return 1;
      return 1;
    }
  }
 
    if ( num_config != 1 ) {
  if ( num_config != 1 ) {
      cerr << "Didn't get exactly one config, but " << num_config << endl;
      cerr << "Didn't get exactly one config, but " << num_config << endl;
      return 1;
      return 1;
    }
  }
 
    egl_surface = eglCreateWindowSurface ( egl_display, ecfg, (void*)win, NULL );
  egl_surface = eglCreateWindowSurface ( egl_display, ecfg, win, NULL );
    if ( egl_surface == EGL_NO_SURFACE ) {
  if ( egl_surface == EGL_NO_SURFACE ) {
      cerr << "Unable to create EGL surface (eglError: " << eglGetError() << ")" << endl;
      cerr << "Unable to create EGL surface (eglError: " << eglGetError() << ")" << endl;
      return 1;
      return 1;
    }
  }
 
    //// egl-contexts collect all state descriptions needed required for operation
  //// egl-contexts collect all state descriptions needed required for operation
    EGLint ctxattr[] = {
  EGLint ctxattr[] = {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
      EGL_NONE
    };
  };
    egl_context = eglCreateContext ( egl_display, ecfg, EGL_NO_CONTEXT, ctxattr );
  egl_context = eglCreateContext ( egl_display, ecfg, EGL_NO_CONTEXT, ctxattr );
    if ( egl_context == EGL_NO_CONTEXT ) {
  if ( egl_context == EGL_NO_CONTEXT ) {
      cerr << "Unable to create EGL context (eglError: " << eglGetError() << ")" << endl;
      cerr << "Unable to create EGL context (eglError: " << eglGetError() << ")" << endl;
      return 1;
      return 1;
    }
  }
 
    //// associate the egl-context with the egl-surface
  //// associate the egl-context with the egl-surface
    eglMakeCurrent( egl_display, egl_surface, egl_surface, egl_context );
  eglMakeCurrent( egl_display, egl_surface, egl_surface, egl_context );
 
 
    ///////  the openGL part  ///////////////////////////////////////////////////////////////
  ///////  the openGL part  ///////////////////////////////////////////////////////////////
 
    GLuint vertexShader  = load_shader ( vertex_src , GL_VERTEX_SHADER  );    // load vertex shader
  GLuint vertexShader  = load_shader ( vertex_src , GL_VERTEX_SHADER  );    // load vertex shader
    GLuint fragmentShader = load_shader ( fragment_src , GL_FRAGMENT_SHADER );  // load fragment shader
  GLuint fragmentShader = load_shader ( fragment_src , GL_FRAGMENT_SHADER );  // load fragment shader
 
    GLuint shaderProgram  = glCreateProgram ();                // create program object
  GLuint shaderProgram  = glCreateProgram ();                // create program object
    glAttachShader ( shaderProgram, vertexShader );            // and attach both...
  glAttachShader ( shaderProgram, vertexShader );            // and attach both...
    glAttachShader ( shaderProgram, fragmentShader );          // ... shaders to it
  glAttachShader ( shaderProgram, fragmentShader );          // ... shaders to it
 
    glLinkProgram ( shaderProgram );    // link the program
  glLinkProgram ( shaderProgram );    // link the program
    glUseProgram  ( shaderProgram );    // and select it for usage
  glUseProgram  ( shaderProgram );    // and select it for usage
 
    //// now get the locations (kind of handle) of the shaders variables
  //// now get the locations (kind of handle) of the shaders variables
    position_loc  = glGetAttribLocation  ( shaderProgram , "position" );
  position_loc  = glGetAttribLocation  ( shaderProgram , "position" );
    phase_loc    = glGetUniformLocation ( shaderProgram , "phase"    );
  phase_loc    = glGetUniformLocation ( shaderProgram , "phase"    );
    offset_loc    = glGetUniformLocation ( shaderProgram , "offset"  );
  offset_loc    = glGetUniformLocation ( shaderProgram , "offset"  );
    if ( position_loc < 0  ||  phase_loc < 0  ||  offset_loc < 0 ) {
  if ( position_loc < 0  ||  phase_loc < 0  ||  offset_loc < 0 ) {
      cerr << "Unable to get uniform location" << endl;
      cerr << "Unable to get uniform location" << endl;
      return 1;
      return 1;
    }
  }
 
 
    const float
  const float
      window_width  = 800.0,
      window_width  = 800.0,
      window_height = 480.0;
      window_height = 480.0;
 
    //// this is needed for time measuring  -->  frames per second
  //// this is needed for time measuring  -->  frames per second
    struct  timezone  tz;
  struct  timezone  tz;
    timeval  t1, t2;
  timeval  t1, t2;
    gettimeofday ( &t1 , &tz );
  gettimeofday ( &t1 , &tz );
    int  num_frames = 0;
  int  num_frames = 0;
 
    bool quit = false;
  bool quit = false;
    while ( !quit ) {    // the main loop
  while ( !quit ) {    // the main loop
 
      while ( XPending ( x_display ) ) {  // check for events from the x-server
      while ( XPending ( x_display ) ) {  // check for events from the x-server
 
          XEvent  xev;
        XEvent  xev;
          XNextEvent( x_display, &xev );
        XNextEvent( x_display, &xev );
 
          if ( xev.type == MotionNotify ) {  // if mouse has moved
        if ( xev.type == MotionNotify ) {  // if mouse has moved
//            cout << "move to: << xev.xmotion.x << "," << xev.xmotion.y << endl;
//            cout << "move to: << xev.xmotion.x << "," << xev.xmotion.y << endl;
            GLfloat window_y  =  (window_height - xev.xmotion.y) - window_height / 2.0;
            GLfloat window_y  =  (window_height - xev.xmotion.y) - window_height / 2.0;
            norm_y            =  window_y / (window_height / 2.0);
            norm_y            =  window_y / (window_height / 2.0);
            GLfloat window_x  =  xev.xmotion.x - window_width / 2.0;
            GLfloat window_x  =  xev.xmotion.x - window_width / 2.0;
            norm_x            =  window_x / (window_width / 2.0);
            norm_x            =  window_x / (window_width / 2.0);
            update_pos = true;
            update_pos = true;
          }
        }
 
//        if ( xev.type == KeyPress )  quit = true; // doesn't work ???
        if ( xev.type == KeyPress )  quit = true;
      }
      }
 
      render();  // now we finally put something on the screen
      render();  // now we finally put something on the screen
 
      if ( ++num_frames % 100 == 0 ) {
      if ( ++num_frames % 100 == 0 ) {
          gettimeofday( &t2, &tz );
        gettimeofday( &t2, &tz );
          float dt  =  t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6;
        float dt  =  t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6;
          cout << "fps: " << num_frames / dt << endl;
        cout << "fps: " << num_frames / dt << endl;
          num_frames = 0;
        num_frames = 0;
          t1 = t2;
        t1 = t2;
      }
      }
//      usleep( 1000*10 );
//      usleep( 1000*10 );
    }
  }
 
 
    ////  cleaning up...
  ////  cleaning up...
    eglDestroyContext ( egl_display, egl_context );
  eglDestroyContext ( egl_display, egl_context );
    eglDestroySurface ( egl_display, egl_surface );
  eglDestroySurface ( egl_display, egl_surface );
    eglTerminate      ( egl_display );
  eglTerminate      ( egl_display );
    XDestroyWindow    ( x_display, win );
  XDestroyWindow    ( x_display, win );
    XCloseDisplay    ( x_display );
  XCloseDisplay    ( x_display );
 
    return 0;
  return 0;
}
}
</source>
   
   
[[Category:Development]]
[[Category:Development]]
[[Category:Fremantle]]
[[Category:Fremantle]]

Latest revision as of 02:51, 26 July 2017

This is a simple program demonstrating how to use OpenGL ES 2.0. It will output this animated spiral, which can be moved around on the screen:

<source lang="cpp"> /* Created by exoticorn ( http://talk.maemo.org/showthread.php?t=37356 )

* edited and commented by André Bergner [endboss]
*
* libraries needed:   libx11-dev, libgles2-dev
*
* compile with:   g++  -lX11 -lEGL -lGLESv2  egl-example.cpp
*/
  1. include <iostream>
  2. include <cstdlib>
  3. include <cstring>

using namespace std;

  1. include <cmath>
  2. include <sys/time.h>
  1. include <X11/Xlib.h>
  2. include <X11/Xatom.h>
  3. include <X11/Xutil.h>
  1. include <GLES2/gl2.h>
  2. include <EGL/egl.h>


const char vertex_src [] = " \

  attribute vec4        position;       \
  varying mediump vec2  pos;            \
  uniform vec4          offset;         \
                                        \
  void main()                           \
  {                                     \
     gl_Position = position + offset;   \
     pos = position.xy;                 \
  }                                     \

";


const char fragment_src [] = " \

  varying mediump vec2    pos;                        \
  uniform mediump float   phase;                      \
                                                      \
  void  main()                                        \
  {                                                   \
     gl_FragColor  =  vec4( 1., 0.9, 0.7, 1.0 ) *     \
       cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y)   \
            + atan(pos.y,pos.x) - phase );            \
  }                                                   \

"; // some more formulas to play with... // cos( 20.*(pos.x*pos.x + pos.y*pos.y) - phase ); // cos( 20.*sqrt(pos.x*pos.x + pos.y*pos.y) + atan(pos.y,pos.x) - phase ); // cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y - 1.8*pos.x*pos.y*pos.y) // + atan(pos.y,pos.x) - phase );


void print_shader_info_log (

  GLuint  shader      // handle to the shader

) {

  GLint  length;
  glGetShaderiv ( shader , GL_INFO_LOG_LENGTH , &length );
  if ( length ) {
     char* buffer  =  new char [ length ];
     glGetShaderInfoLog ( shader , length , NULL , buffer );
     cout << "shader info: " <<  buffer << flush;
     delete [] buffer;
     GLint success;
     glGetShaderiv( shader, GL_COMPILE_STATUS, &success );
     if ( success != GL_TRUE )   exit ( 1 );
  }

}


GLuint load_shader (

  const char  *shader_source,
  GLenum       type

) {

  GLuint  shader = glCreateShader( type );
  glShaderSource  ( shader , 1 , &shader_source , NULL );
  glCompileShader ( shader );
  print_shader_info_log ( shader );
  return shader;

}


Display *x_display; Window win; EGLDisplay egl_display; EGLContext egl_context; EGLSurface egl_surface;

GLfloat

  norm_x    =  0.0,
  norm_y    =  0.0,
  offset_x  =  0.0,
  offset_y  =  0.0,
  p1_pos_x  =  0.0,
  p1_pos_y  =  0.0;

GLint

  phase_loc,
  offset_loc,
  position_loc;


bool update_pos = false;

const float vertexArray[] = {

  0.0,  0.5,  0.0,
 -0.5,  0.0,  0.0,
  0.0, -0.5,  0.0,
  0.5,  0.0,  0.0,
  0.0,  0.5,  0.0 

};


void render() {

  static float  phase = 0;
  static int    donesetup = 0;
  static XWindowAttributes gwa;
  //// draw
  if ( !donesetup ) {
     XWindowAttributes  gwa;
     XGetWindowAttributes ( x_display , win , &gwa );
     glViewport ( 0 , 0 , gwa.width , gwa.height );
     glClearColor ( 0.08 , 0.06 , 0.07 , 1.);    // background color
     donesetup = 1;
  }
  glClear ( GL_COLOR_BUFFER_BIT );
  glUniform1f ( phase_loc , phase );  // write the value of phase to the shaders phase
  phase  =  fmodf ( phase + 0.5f , 2.f * 3.141f );    // and update the local variable
  if ( update_pos ) {  // if the position of the texture has changed due to user action
     GLfloat old_offset_x  =  offset_x;
     GLfloat old_offset_y  =  offset_y;
     offset_x  =  norm_x - p1_pos_x;
     offset_y  =  norm_y - p1_pos_y;
     p1_pos_x  =  norm_x;
     p1_pos_y  =  norm_y;
     offset_x  +=  old_offset_x;
     offset_y  +=  old_offset_y;
     update_pos = false;
  }
  glUniform4f ( offset_loc  ,  offset_x , offset_y , 0.0 , 0.0 );
  glVertexAttribPointer ( position_loc, 3, GL_FLOAT, false, 0, vertexArray );
  glEnableVertexAttribArray ( position_loc );
  glDrawArrays ( GL_TRIANGLE_STRIP, 0, 5 );
  eglSwapBuffers ( egl_display, egl_surface );  // get the rendered buffer to the screen

}


////////////////////////////////////////////////////////////////////////////////////////////


int main() {

  ///////  the X11 part  //////////////////////////////////////////////////////////////////
  // in the first part the program opens a connection to the X11 window manager
  //
  x_display = XOpenDisplay ( NULL );   // open the standard display (the primary screen)
  if ( x_display == NULL ) {
     cerr << "cannot connect to X server" << endl;
     return 1;
  }
  Window root  =  DefaultRootWindow( x_display );   // get the root window (usually the whole screen)
  XSetWindowAttributes  swa;
  swa.event_mask  =  ExposureMask | PointerMotionMask | KeyPressMask;
  win  =  XCreateWindow (   // create a window with the provided parameters
             x_display, root,
             0, 0, 800, 480,   0,
             CopyFromParent, InputOutput,
             CopyFromParent, CWEventMask,
             &swa );
  XSetWindowAttributes  xattr;
  Atom  atom;
  int   one = 1;
  xattr.override_redirect = False;
  XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr );
  atom = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", True );
  XChangeProperty (
     x_display, win,
     XInternAtom ( x_display, "_NET_WM_STATE", True ),
     XA_ATOM,  32,  PropModeReplace,
     (unsigned char*) &atom,  1 );
  XChangeProperty (
     x_display, win,
     XInternAtom ( x_display, "_HILDON_NON_COMPOSITED_WINDOW", False ),
     XA_INTEGER,  32,  PropModeReplace,
     (unsigned char*) &one,  1);
  XWMHints hints;
  hints.input = True;
  hints.flags = InputHint;
  XSetWMHints(x_display, win, &hints);
  XMapWindow ( x_display , win );             // make the window visible on the screen
  XStoreName ( x_display , win , "GL test" ); // give the window a name
  //// get identifiers for the provided atom name strings
  Atom wm_state   = XInternAtom ( x_display, "_NET_WM_STATE", False );
  Atom fullscreen = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", False );
  XEvent xev;
  memset ( &xev, 0, sizeof(xev) );
  xev.type                 = ClientMessage;
  xev.xclient.window       = win;
  xev.xclient.message_type = wm_state;
  xev.xclient.format       = 32;
  xev.xclient.data.l[0]    = 1;
  xev.xclient.data.l[1]    = fullscreen;
  XSendEvent (                // send an event mask to the X-server
     x_display,
     DefaultRootWindow ( x_display ),
     False,
     SubstructureNotifyMask,
     &xev );


  ///////  the egl part  //////////////////////////////////////////////////////////////////
  //  egl provides an interface to connect the graphics related functionality of openGL ES
  //  with the windowing interface and functionality of the native operation system (X11
  //  in our case.
  egl_display  =  eglGetDisplay( (EGLNativeDisplayType) x_display );
  if ( egl_display == EGL_NO_DISPLAY ) {
     cerr << "Got no EGL display." << endl;
     return 1;
  }
  if ( !eglInitialize( egl_display, NULL, NULL ) ) {
     cerr << "Unable to initialize EGL" << endl;
     return 1;
  }
  EGLint attr[] = {       // some attributes to set up our egl-interface
     EGL_BUFFER_SIZE, 16,
     EGL_RENDERABLE_TYPE,
     EGL_OPENGL_ES2_BIT,
     EGL_NONE
  };
  EGLConfig  ecfg;
  EGLint     num_config;
  if ( !eglChooseConfig( egl_display, attr, &ecfg, 1, &num_config ) ) {
     cerr << "Failed to choose config (eglError: " << eglGetError() << ")" << endl;
     return 1;
  }
  if ( num_config != 1 ) {
     cerr << "Didn't get exactly one config, but " << num_config << endl;
     return 1;
  }
  egl_surface = eglCreateWindowSurface ( egl_display, ecfg, win, NULL );
  if ( egl_surface == EGL_NO_SURFACE ) {
     cerr << "Unable to create EGL surface (eglError: " << eglGetError() << ")" << endl;
     return 1;
  }
  //// egl-contexts collect all state descriptions needed required for operation
  EGLint ctxattr[] = {
     EGL_CONTEXT_CLIENT_VERSION, 2,
     EGL_NONE
  };
  egl_context = eglCreateContext ( egl_display, ecfg, EGL_NO_CONTEXT, ctxattr );
  if ( egl_context == EGL_NO_CONTEXT ) {
     cerr << "Unable to create EGL context (eglError: " << eglGetError() << ")" << endl;
     return 1;
  }
  //// associate the egl-context with the egl-surface
  eglMakeCurrent( egl_display, egl_surface, egl_surface, egl_context );


  ///////  the openGL part  ///////////////////////////////////////////////////////////////
  GLuint vertexShader   = load_shader ( vertex_src , GL_VERTEX_SHADER  );     // load vertex shader
  GLuint fragmentShader = load_shader ( fragment_src , GL_FRAGMENT_SHADER );  // load fragment shader
  GLuint shaderProgram  = glCreateProgram ();                 // create program object
  glAttachShader ( shaderProgram, vertexShader );             // and attach both...
  glAttachShader ( shaderProgram, fragmentShader );           // ... shaders to it
  glLinkProgram ( shaderProgram );    // link the program
  glUseProgram  ( shaderProgram );    // and select it for usage
  //// now get the locations (kind of handle) of the shaders variables
  position_loc  = glGetAttribLocation  ( shaderProgram , "position" );
  phase_loc     = glGetUniformLocation ( shaderProgram , "phase"    );
  offset_loc    = glGetUniformLocation ( shaderProgram , "offset"   );
  if ( position_loc < 0  ||  phase_loc < 0  ||  offset_loc < 0 ) {
     cerr << "Unable to get uniform location" << endl;
     return 1;
  }


  const float
     window_width  = 800.0,
     window_height = 480.0;
  //// this is needed for time measuring  -->  frames per second
  struct  timezone  tz;
  timeval  t1, t2;
  gettimeofday ( &t1 , &tz );
  int  num_frames = 0;
  bool quit = false;
  while ( !quit ) {    // the main loop
     while ( XPending ( x_display ) ) {   // check for events from the x-server
        XEvent  xev;
        XNextEvent( x_display, &xev );
        if ( xev.type == MotionNotify ) {  // if mouse has moved

// cout << "move to: << xev.xmotion.x << "," << xev.xmotion.y << endl;

           GLfloat window_y  =  (window_height - xev.xmotion.y) - window_height / 2.0;
           norm_y            =  window_y / (window_height / 2.0);
           GLfloat window_x  =  xev.xmotion.x - window_width / 2.0;
           norm_x            =  window_x / (window_width / 2.0);
           update_pos = true;
        }
        if ( xev.type == KeyPress )   quit = true;
     }
     render();   // now we finally put something on the screen
     if ( ++num_frames % 100 == 0 ) {
        gettimeofday( &t2, &tz );
        float dt  =  t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6;
        cout << "fps: " << num_frames / dt << endl;
        num_frames = 0;
        t1 = t2;
     }

// usleep( 1000*10 );

  }


  ////  cleaning up...
  eglDestroyContext ( egl_display, egl_context );
  eglDestroySurface ( egl_display, egl_surface );
  eglTerminate      ( egl_display );
  XDestroyWindow    ( x_display, win );
  XCloseDisplay     ( x_display );
  return 0;

} </source>