Editing SimpleGL example
Warning: You are not logged in.
Your IP address will be recorded in this page's edit history.
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
- | + | /* Created by exoticorn (http://talk.maemo.org/showthread.php?t=37356 */ | |
- | + | #include <stdio.h> | |
- | + | #include <stdlib.h> | |
- | + | #include <X11/Xatom.h> | |
- | + | #include <X11/Xlib.h> | |
- | /* Created by exoticorn ( http://talk.maemo.org/showthread.php?t=37356 | + | #include <X11/Xutil.h> |
- | + | #include <GLES2/gl2.h> | |
- | + | #include <EGL/egl.h> | |
- | + | #include <math.h> | |
- | + | #include <sys/time.h> | |
- | + | #include <unistd.h> | |
- | + | #include <string.h> | |
- | + | ||
- | #include | + | const char* vertexSrc = "attribute vec4 position; varying mediump vec2 pos; uniform vec4 offset; void main() { gl_Position = position + offset; pos = position.xy; }"; |
- | #include | + | const char* fragmentSrc = "varying mediump vec2 pos; uniform mediump float phase; void main() { gl_FragColor = vec4(1, 1, 1, 1) * sin((pos.x * pos.x + pos.y * pos.y) * 40.0 + phase); }"; |
- | #include | + | |
- | + | void printShaderInfoLog(GLuint shader) { | |
- | + | GLint length; | |
- | #include | + | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); |
- | #include | + | if(length) { |
- | + | char* buffer = new char[length]; | |
- | #include | + | glGetShaderInfoLog(shader, length, NULL, buffer); |
- | #include | + | printf("%s", buffer); |
- | #include | + | delete [] buffer; |
- | + | GLint success; | |
- | #include | + | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); |
- | #include | + | if(success != GL_TRUE) { |
- | + | exit(1); | |
- | + | } | |
- | + | ||
- | const char | + | |
- | " | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | "; | + | |
- | + | ||
- | + | ||
- | const char | + | |
- | " | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | "; | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | void | + | |
- | + | ||
- | + | ||
- | ) | + | |
- | { | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | { | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | } | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
} | } | ||
- | + | } | |
- | + | ||
- | + | GLuint createShader(GLenum type, const char* pSource) { | |
- | + | GLuint shader = glCreateShader(type); | |
- | + | glShaderSource(shader, 1, &pSource, NULL); | |
- | + | glCompileShader(shader); | |
- | + | printShaderInfoLog(shader); | |
- | + | return shader; | |
- | + | } | |
- | + | ||
- | + | Display* dpy; | |
- | + | Window win; | |
- | + | EGLDisplay edpy; | |
- | // | + | EGLContext ectxt; |
- | + | int phaseLocation; | |
- | + | GLfloat norm_x; | |
- | + | GLfloat norm_y; | |
- | + | GLfloat offset_x = 0.0; | |
- | + | GLfloat offset_y = 0.0; | |
- | + | GLfloat p1_pos_x; | |
- | + | GLfloat p1_pos_y; | |
- | + | ||
- | + | GLint offset; | |
- | + | EGLSurface esfc; | |
- | + | bool update_pos = false; | |
- | + | ||
- | + | const float vertexArray[] = { | |
+ | -0.85, -1, 0, 1, | ||
+ | -1, -0.7, 0, 1, | ||
+ | -0.7, -0.7, 0, 1 | ||
+ | }; | ||
+ | |||
+ | void render() { | ||
+ | static float offset_blah = 0; | ||
+ | static int donesetup=0; | ||
+ | static XWindowAttributes gwa; | ||
+ | |||
+ | // draw | ||
+ | |||
+ | if (!donesetup) { | ||
+ | XWindowAttributes gwa; | ||
+ | XGetWindowAttributes(dpy, win, &gwa); | ||
+ | glViewport(0, 0, gwa.width, gwa.height); | ||
+ | glClearColor(0, 1, 0, 1); | ||
+ | donesetup = 1; | ||
+ | } | ||
+ | glClear(GL_COLOR_BUFFER_BIT); | ||
+ | |||
+ | glUniform1f(phaseLocation, offset_blah); | ||
+ | |||
+ | if (update_pos) { | ||
+ | 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, offset_x, offset_y, 0, 0); | ||
+ | |||
+ | glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, vertexArray); | ||
+ | glEnableVertexAttribArray(0); | ||
+ | glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); | ||
+ | |||
+ | eglSwapBuffers(edpy, esfc); | ||
+ | |||
+ | offset_blah = fmodf(offset_blah + 0.5, 2*3.141f); | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | dpy = XOpenDisplay(NULL); | ||
+ | if(dpy == NULL) { | ||
+ | printf("cannot connect to X server\n"); | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | Window root = DefaultRootWindow(dpy); | ||
+ | |||
+ | XSetWindowAttributes swa; | ||
+ | swa.event_mask = ExposureMask | PointerMotionMask; | ||
+ | |||
+ | win = XCreateWindow(dpy, root, 0, 0, 600, 400, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &swa); | ||
+ | |||
+ | XSetWindowAttributes xattr; | ||
+ | Atom atom; | ||
+ | int one = 1; | ||
+ | |||
+ | xattr.override_redirect = False; | ||
+ | XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &xattr); | ||
+ | |||
+ | atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", True); | ||
+ | XChangeProperty(dpy, win, XInternAtom(dpy, "_NET_WM_STATE", True), | ||
+ | XA_ATOM, 32, PropModeReplace, | ||
+ | (unsigned char *) &atom, 1); | ||
+ | |||
+ | XChangeProperty(dpy, win, XInternAtom(dpy, "_HILDON_NON_COMPOSITED_WINDOW", True), | ||
+ | XA_INTEGER, 32, PropModeReplace, | ||
+ | (unsigned char *) &one, 1); | ||
+ | |||
+ | XMapWindow(dpy, win); | ||
+ | |||
+ | XStoreName(dpy, win, "GL test"); | ||
+ | |||
+ | Atom wm_state = XInternAtom(dpy, "_NET_WM_STATE", False); | ||
+ | Atom fullscreen = XInternAtom(dpy, "_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(dpy, DefaultRootWindow(dpy), False, SubstructureNotifyMask, &xev); | ||
+ | |||
+ | edpy = eglGetDisplay((EGLNativeDisplayType)dpy); | ||
+ | if(edpy == EGL_NO_DISPLAY) { | ||
+ | printf("Got no EGL display\n"); | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | if(!eglInitialize(edpy, NULL, NULL)) { | ||
+ | printf("Unable to initialize EGL\n"); | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | EGLint attr[] = { | ||
+ | EGL_BUFFER_SIZE, 16, | ||
+ | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | ||
+ | EGL_NONE | ||
+ | }; | ||
+ | |||
+ | EGLConfig ecfg; | ||
+ | EGLint num_config; | ||
+ | if(!eglChooseConfig(edpy, attr, &ecfg, 1, &num_config)) { | ||
+ | printf("Failed to choose config (%x)\n", eglGetError()); | ||
+ | return 1; | ||
+ | } | ||
+ | if(num_config != 1) { | ||
+ | printf("Didn't get exactly one config, but %d\n", num_config); | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | esfc = eglCreateWindowSurface(edpy, ecfg, (void*)win, NULL); | ||
+ | if(esfc == EGL_NO_SURFACE) { | ||
+ | printf("Unable to create EGL surface (%x)\n", eglGetError()); | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | EGLint ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; | ||
+ | ectxt = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, ctxattr); | ||
+ | if(ectxt == EGL_NO_CONTEXT) { | ||
+ | printf("Unable to create EGL context (%x)\n", eglGetError()); | ||
+ | return 1; | ||
+ | } | ||
+ | eglMakeCurrent(edpy, esfc, esfc, ectxt); | ||
+ | |||
+ | GLuint shaderProgram = glCreateProgram(); | ||
+ | GLuint vertexShader = createShader(GL_VERTEX_SHADER, vertexSrc); | ||
+ | GLuint fragmentShader = createShader(GL_FRAGMENT_SHADER, fragmentSrc); | ||
+ | |||
+ | glAttachShader(shaderProgram, vertexShader); | ||
+ | glAttachShader(shaderProgram, fragmentShader); | ||
+ | |||
+ | glLinkProgram(shaderProgram); | ||
+ | |||
+ | glUseProgram(shaderProgram); | ||
+ | |||
+ | phaseLocation = glGetUniformLocation(shaderProgram, "phase"); | ||
+ | offset = glGetUniformLocation(shaderProgram, "offset"); | ||
+ | if(phaseLocation < 0) { | ||
+ | printf("Unable to get uniform location\n"); | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | bool quit = false; | ||
+ | |||
+ | timeval startTime; | ||
+ | timezone tz; | ||
+ | gettimeofday(&startTime, &tz); | ||
+ | int numFrames = 0; | ||
+ | |||
+ | float window_width = 800.0; | ||
+ | float window_height = 480.0; | ||
+ | |||
+ | norm_x = -0.85; | ||
+ | norm_y = -1; | ||
+ | p1_pos_x = -0.85; | ||
+ | p1_pos_y = -1; | ||
+ | |||
+ | |||
+ | |||
+ | while(!quit) { | ||
+ | |||
+ | while(XPending(dpy)) { | ||
+ | XEvent xev; | ||
+ | XNextEvent(dpy, &xev); | ||
+ | |||
+ | if(xev.type == MotionNotify) { | ||
+ | //printf("move to: (%d,%d)\n", xev.xmotion.x, xev.xmotion.y); | ||
+ | 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; | ||
+ | //quit = true; | ||
+ | } | ||
+ | } | ||
+ | render(); | ||
+ | numFrames++; | ||
+ | if(numFrames % 100 == 0) { | ||
+ | timeval now; | ||
+ | gettimeofday(&now, &tz); | ||
+ | float delta = now.tv_sec - startTime.tv_sec + (now.tv_usec - startTime.tv_usec) * 0.000001f; | ||
+ | printf("fps: %f\n", numFrames / delta); | ||
+ | } | ||
+ | |||
+ | usleep(1000*30); | ||
+ | } | ||
+ | |||
+ | eglDestroyContext(edpy, ectxt); | ||
+ | eglDestroySurface(edpy, esfc); | ||
+ | eglTerminate(edpy); | ||
+ | XDestroyWindow(dpy, win); | ||
+ | XCloseDisplay(dpy); | ||
- | + | return 0; | |
- | + | } |
Learn more about Contributing to the wiki.