SimpleGL example: Difference between revisions
imported>mr_smiley New page: #include <stdio.h> #include <stdlib.h> #include <X11/Xatom.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <GLES2/gl2.h> #include <EGL/egl.h> #include <math.h> #include <... |
Change only_if_exists to False, then the atom is created if it does not exist to avoid return invalid atom. |
||
| (13 intermediate revisions by 6 users 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: | |||
[[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] | |||
#include < | * | ||
* libraries needed: libx11-dev, libgles2-dev | |||
* | |||
#include < | * 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: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 */
- 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>
