SimpleGL example

m (OpenGL ES 2 link)
(Change only_if_exists to False, then the atom is created if it does not exist to avoid return invalid atom.)
 
(6 intermediate revisions not shown)
Line 1: Line 1:
-
This is a simple program demonstrating how to use [[OpenGL-ES#OpenGL_variants|PpenGL 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 | KeyPressMask;
+
              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;
+
        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:

Image:Egl-example_output.png

/* 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
 */
 
#include  <iostream>
#include  <cstdlib>
#include  <cstring>
using namespace std;
 
#include  <cmath>
#include  <sys/time.h>
 
#include  <X11/Xlib.h>
#include  <X11/Xatom.h>
#include  <X11/Xutil.h>
 
#include  <GLES2/gl2.h>
#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;
}