From f50ddaa63c563cf2483e9c61d22086a05cfd2115 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Wed, 9 Nov 2011 12:45:20 +0100 Subject: Added texture_distortion_glsl and x11argb_opengl_glsl codesamples --- .../x11argb_opengl_glsl/x11argb_opengl_glsl.c | 529 +++++++++++++++++++++ 1 file changed, 529 insertions(+) create mode 100644 samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c (limited to 'samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c') diff --git a/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c b/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c new file mode 100644 index 0000000..f7fc68e --- /dev/null +++ b/samples/OpenGL/x11argb_opengl_glsl/x11argb_opengl_glsl.c @@ -0,0 +1,529 @@ +/*------------------------------------------------------------------------ + * A demonstration of OpenGL in a ARGB window + * => support for composited window transparency + * + * (c) 2011 by Wolfgang 'datenwolf' Draxinger + * See me at comp.graphics.api.opengl and StackOverflow.com + + * License agreement: This source code is provided "as is". You + * can use this source code however you want for your own personal + * use. If you give this source code to anybody else then you must + * leave this message in it. + * + * This program is based on the simplest possible + * Linux OpenGL program by FTB (see info below) + + The simplest possible Linux OpenGL program? Maybe... + + (c) 2002 by FTB. See me in comp.graphics.api.opengl + + -- + <\___/> + / O O \ + \_____/ FTB. + +------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define USE_CHOOSE_FBCONFIG +#define USE_GLX_CREATE_WINDOW + +static const GLchar *vertex_shader_source = +"#version 120\n" +"void main()" +"{" +" gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;" +" gl_TexCoord[0] = gl_MultiTexCoord0;" +" gl_FrontColor = gl_Color;" +" gl_BackColor = gl_Color;" +"}\0"; +GLuint shaderVertex = 0; + +static const GLchar *fragment_shader_source = +"#version 120\n" +"uniform sampler2D texCMYK;\n" +"uniform sampler2D texRGB;\n" +"uniform float T;\n" +"const float pi = 3.14159265;\n" +"void main()\n" +"{\n" +" float ts = gl_TexCoord[0].s;\n" +" vec2 mod_texcoord = gl_TexCoord[0].st*vec2(1., 2.) + vec2(0, -0.5 + 0.5*sin(T + 1.5*ts*pi));\n" +" if( mod_texcoord.t < 0. || mod_texcoord.t > 1. ) { discard; }\n" +" gl_FragColor = -texture2D(texCMYK, mod_texcoord) + texture2D(texRGB, gl_TexCoord[0].st);\n" +" gl_FragColor.a = 1.0;\n" +"}\n\0"; +GLuint shaderFragment = 0; + +GLuint shaderProgram = 0; + +#define TEX_CMYK_WIDTH 2 +#define TEX_CMYK_HEIGHT 2 +GLubyte textureDataCMYK[TEX_CMYK_WIDTH * TEX_CMYK_HEIGHT][3] = { + {0x00, 0xff, 0xff}, {0xff, 0x00, 0xff}, + {0xff, 0xff, 0x00}, {0x00, 0x00, 0x00} +}; +GLuint texCMYK = 0; + +#define TEX_RGB_WIDTH 2 +#define TEX_RGB_HEIGHT 2 +GLubyte textureDataRGB[TEX_RGB_WIDTH * TEX_RGB_HEIGHT][3] = { + {0x00, 0x00, 0xff}, {0xff, 0xff, 0xff}, + {0xff, 0x00, 0x00}, {0x00, 0xff, 0x00} +}; +GLuint texRGB = 0; + +/* 6----7 + /| /| + 3----2 | + | 5--|-4 + |/ |/ + 0----1 +*/ +GLfloat cube_vertices[][8] = { + /* X Y Z Nx Ny Nz S T */ + {-1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 0 + { 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0}, // 1 + { 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0}, // 2 + {-1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0}, // 3 + + { 1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0}, // 4 + {-1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0}, // 5 + {-1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 1.0}, // 6 + { 1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0}, // 7 + + {-1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0}, // 5 + {-1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 0.0}, // 0 + {-1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 1.0}, // 3 + {-1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0}, // 6 + + { 1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 1 + { 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0}, // 4 + { 1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0}, // 7 + { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0}, // 2 + + {-1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0}, // 5 + { 1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 1.0, 0.0}, // 4 + { 1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 1.0, 1.0}, // 1 + {-1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0}, // 0 + + {-1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 3 + { 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0}, // 2 + { 1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 1.0}, // 7 + {-1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0}, // 6 +}; + +static void fatalError(const char *why) +{ + fprintf(stderr, "%s", why); + exit(0x666); +} + +static int Xscreen; +static Atom del_atom; +static Colormap cmap; +static Display *Xdisplay; +static XVisualInfo *visual; +static XRenderPictFormat *pict_format; +static GLXFBConfig *fbconfigs, fbconfig; +static int numfbconfigs; +static GLXContext render_context; +static Window Xroot, window_handle; +static GLXWindow glX_window_handle; +static int width, height; + +static int VisData[] = { +GLX_RENDER_TYPE, GLX_RGBA_BIT, +GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, +GLX_DOUBLEBUFFER, True, +GLX_RED_SIZE, 8, +GLX_GREEN_SIZE, 8, +GLX_BLUE_SIZE, 8, +GLX_ALPHA_SIZE, 8, +GLX_DEPTH_SIZE, 16, +None +}; + +static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg) +{ + return d && e && arg && (e->type == MapNotify) && (e->xmap.window == *(Window*)arg); +} + +static void describe_fbconfig(GLXFBConfig fbconfig) +{ + int doublebuffer; + int red_bits, green_bits, blue_bits, alpha_bits, depth_bits; + + glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DOUBLEBUFFER, &doublebuffer); + glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_RED_SIZE, &red_bits); + glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_GREEN_SIZE, &green_bits); + glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_BLUE_SIZE, &blue_bits); + glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_ALPHA_SIZE, &alpha_bits); + glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DEPTH_SIZE, &depth_bits); + + fprintf(stderr, "FBConfig selected:\n" + "Doublebuffer: %s\n" + "Red Bits: %d, Green Bits: %d, Blue Bits: %d, Alpha Bits: %d, Depth Bits: %d\n", + doublebuffer == True ? "Yes" : "No", + red_bits, green_bits, blue_bits, alpha_bits, depth_bits); +} + +static void createTheWindow() +{ + XEvent event; + int x,y, attr_mask; + XSizeHints hints; + XWMHints *startup_state; + XTextProperty textprop; + XSetWindowAttributes attr = {0,}; + static char *title = "FTB's little OpenGL example - ARGB extension by WXD"; + + Xdisplay = XOpenDisplay(NULL); + if (!Xdisplay) { + fatalError("Couldn't connect to X server\n"); + } + Xscreen = DefaultScreen(Xdisplay); + Xroot = RootWindow(Xdisplay, Xscreen); + + fbconfigs = glXChooseFBConfig(Xdisplay, Xscreen, VisData, &numfbconfigs); + fbconfig = 0; + for(int i = 0; ivisual); + if(!pict_format) + continue; + + fbconfig = fbconfigs[i]; + if(pict_format->direct.alphaMask > 0) { + break; + } + } + + if(!fbconfig) { + fatalError("No matching FB config found"); + } + + describe_fbconfig(fbconfig); + + /* Create a colormap - only needed on some X clients, eg. IRIX */ + cmap = XCreateColormap(Xdisplay, Xroot, visual->visual, AllocNone); + + attr.colormap = cmap; + attr.background_pixmap = None; + attr.border_pixmap = None; + attr.border_pixel = 0; + attr.event_mask = + StructureNotifyMask | + EnterWindowMask | + LeaveWindowMask | + ExposureMask | + ButtonPressMask | + ButtonReleaseMask | + OwnerGrabButtonMask | + KeyPressMask | + KeyReleaseMask; + + attr_mask = + CWBackPixmap| + CWColormap| + CWBorderPixel| + CWEventMask; + + width = DisplayWidth(Xdisplay, DefaultScreen(Xdisplay))/2; + height = DisplayHeight(Xdisplay, DefaultScreen(Xdisplay))/2; + x=width/2, y=height/2; + + window_handle = XCreateWindow( Xdisplay, + Xroot, + x, y, width, height, + 0, + visual->depth, + InputOutput, + visual->visual, + attr_mask, &attr); + + if( !window_handle ) { + fatalError("Couldn't create the window\n"); + } + +#ifdef USE_GLX_CREATE_WINDOW + int glXattr[] = { None }; + glX_window_handle = glXCreateWindow(Xdisplay, fbconfig, window_handle, glXattr); + if( !glX_window_handle ) { + fatalError("Couldn't create the GLX window\n"); + } +#else + glX_window_handle = window_handle; +#endif + + textprop.value = (unsigned char*)title; + textprop.encoding = XA_STRING; + textprop.format = 8; + textprop.nitems = strlen(title); + + hints.x = x; + hints.y = y; + hints.width = width; + hints.height = height; + hints.flags = USPosition|USSize; + + startup_state = XAllocWMHints(); + startup_state->initial_state = NormalState; + startup_state->flags = StateHint; + + XSetWMProperties(Xdisplay, window_handle,&textprop, &textprop, + NULL, 0, + &hints, + startup_state, + NULL); + + XFree(startup_state); + + XMapWindow(Xdisplay, window_handle); + XIfEvent(Xdisplay, &event, WaitForMapNotify, (char*)&window_handle); + + if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None) { + XSetWMProtocols(Xdisplay, window_handle, &del_atom, 1); + } +} + +static void createTheRenderContext() +{ + int dummy; + if (!glXQueryExtension(Xdisplay, &dummy, &dummy)) { + fatalError("OpenGL not supported by X server\n"); + } + + render_context = glXCreateNewContext(Xdisplay, fbconfig, GLX_RGBA_TYPE, 0, True); + if (!render_context) { + fatalError("Failed to create a GL context\n"); + } + + if (!glXMakeContextCurrent(Xdisplay, glX_window_handle, glX_window_handle, render_context)) { + fatalError("glXMakeCurrent failed for window\n"); + } + + glewInit(); +} + +static int updateTheMessageQueue() +{ + XEvent event; + XConfigureEvent *xc; + + while (XPending(Xdisplay)) + { + XNextEvent(Xdisplay, &event); + switch (event.type) + { + case ClientMessage: + if (event.xclient.data.l[0] == del_atom) + { + return 0; + } + break; + + case ConfigureNotify: + xc = &(event.xconfigure); + width = xc->width; + height = xc->height; + break; + } + } + return 1; +} + +static int check_extensions(void) +{ + if( !GLEW_ARB_vertex_shader || + !GLEW_ARB_fragment_shader ) { + fputs("Required OpenGL functionality not supported by system.\n", stderr); + return 0; + } + + return 1; +} + +static int check_shader_compilation(GLuint shader) +{ + GLint n; + glGetShaderiv(shader, GL_COMPILE_STATUS, &n); + if( n == GL_FALSE ) { + GLchar *info_log; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &n); + info_log = malloc(n); + glGetShaderInfoLog(shader, n, &n, info_log); + fprintf(stderr, "Shader compilation failed: %*s\n", n, info_log); + free(info_log); + return 0; + } + return 1; +} + +static int init_resources(void) +{ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + glGenTextures(1, &texCMYK); + glBindTexture(GL_TEXTURE_2D, texCMYK); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, TEX_CMYK_WIDTH, TEX_CMYK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, textureDataCMYK); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glGenTextures(1, &texRGB); + glBindTexture(GL_TEXTURE_2D, texRGB); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, TEX_RGB_WIDTH, TEX_RGB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, textureDataRGB); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + shaderVertex = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(shaderVertex, 1, (const GLchar**)&vertex_shader_source, NULL); + glCompileShader(shaderVertex); + if( !check_shader_compilation(shaderVertex) ) + return 0; + + shaderFragment = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(shaderFragment, 1, (const GLchar**)&fragment_shader_source, NULL); + glCompileShader(shaderFragment); + if( !check_shader_compilation(shaderFragment) ) + return 0; + + shaderProgram = glCreateProgram(); + glAttachShader(shaderProgram, shaderVertex); + glAttachShader(shaderProgram, shaderFragment); + glLinkProgram(shaderProgram); + + return 1; +} + +static void bind_sampler_to_unit_with_texture(GLchar const * const sampler_name, GLuint texture_unit, GLuint texture) +{ + glActiveTexture(GL_TEXTURE0 + texture_unit); + glBindTexture(GL_TEXTURE_2D, texture); + GLuint loc_sampler = glGetUniformLocation(shaderProgram, sampler_name); + glUniform1i(loc_sampler, texture_unit); +} + +static void pushModelview() +{ + GLenum prev_matrix_mode; + glGetIntegerv(GL_MATRIX_MODE, &prev_matrix_mode); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glMatrixMode(prev_matrix_mode); +} + +static void popModelview() +{ + GLenum prev_matrix_mode; + glGetIntegerv(GL_MATRIX_MODE, &prev_matrix_mode); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glMatrixMode(prev_matrix_mode); +} + + +static void draw_cube(void) +{ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glVertexPointer(3, GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][0]); + glNormalPointer(GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][3]); + glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][6]); + + glDrawArrays(GL_QUADS, 0, 24); +} + +static void redrawTheWindow(double T) +{ + int const window_width = width; + int const window_height = height; + const float window_aspect = (float)window_width / (float)window_height; + + glDisable(GL_SCISSOR_TEST); + + glClearColor(0., 0., 0., 0.0); + glClearDepth(1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + glViewport(0, 0, window_width, window_height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-window_aspect, window_aspect, -1, 1, 2.5, 10); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -5); + + glDisable(GL_BLEND); + + pushModelview(); + glRotatef(T * 0.1 * 180, 0., 1., 0.); + glRotatef(T * 0.1 * 60, 1., 0., 0.); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glUseProgram(shaderProgram); + glUniform1f(glGetUniformLocation(shaderProgram, "T"), T); + bind_sampler_to_unit_with_texture("texCMYK", 0, texCMYK); + bind_sampler_to_unit_with_texture("texRGB", 1, texRGB); + + draw_cube(); + popModelview(); + + glXSwapBuffers(Xdisplay, glX_window_handle); +} + +static double getftime(void) { + static long long offset = 0; + long long t; + struct timeval timeofday; + + gettimeofday(&timeofday, NULL); + t = (long long)timeofday.tv_sec * 1000000 + (long long)timeofday.tv_usec; + + if(offset == 0) + offset = t; + + return (double)(offset - t) * 1.e-6; +} + +int main(int argc, char *argv[]) +{ + + createTheWindow(); + createTheRenderContext(); + + if( !check_extensions() ) + return -1; + + if( !init_resources() ) + return -1; + + while (updateTheMessageQueue()) { + redrawTheWindow(getftime()); + } + + return 0; +} + -- cgit v1.2.3