SimpleGL example
(Change only_if_exists to False, then the atom is created if it does not exist to avoid return invalid atom.) |
|||
(10 intermediate revisions not shown) | |||
Line 1: | Line 1: | ||
- | + | 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: | |
- | + | ||
- | #include < | + | [[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 | |
- | + | */ | |
- | + | ||
- | + | #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; | |
- | + | } | |
- | + | </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:
/* 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; }
- This page was last modified on 26 July 2017, at 02:51.
- This page has been accessed 70,621 times.