opengl_x11

Playing with OpenGL
git clone git://bsandro.tech/opengl_x11
Log | Files | Refs | README | LICENSE

main2.c (8008B)


      1 /* tesselation */
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <time.h>
      6 #include <unistd.h>
      7 #include <math.h>
      8 #include <X11/X.h>
      9 #include <X11/Xlib.h>
     10 #define GL_GLEXT_PROTOTYPES 1
     11 #include <GL/gl.h>
     12 #include <GL/glx.h>
     13 #include <GL/glu.h>
     14 
     15 #ifndef CALLBACK
     16 #define CALLBACK void (*)(void)
     17 #endif
     18 
     19 static const double current_ts() {
     20     struct timespec ts;
     21     timespec_get(&ts, TIME_UTC);
     22     return (double)ts.tv_sec + (double)ts.tv_nsec/1e9;
     23 }
     24 
     25 static double t_started;
     26 
     27 static void tessCbBegin(GLenum type) {
     28     glBegin(type);
     29     printf("glBegin(%d)\n", type);
     30 }
     31 
     32 static void tessCbVertex(void *data) {
     33     const float scale = 0.2f;
     34     const GLdouble *p = data;
     35     glVertex3d(p[0]*scale, p[1]*scale, p[2]);
     36     printf("glVertex3d(%.1f, %.1f, %.1f)\n", *p, *(p+1), *(p+2));
     37 }
     38 
     39 static void tessCbEnd() {
     40     glEnd();
     41     printf("glEnd()\n");
     42 }
     43 
     44 static void tessCbError(GLenum errno) {
     45     printf("tesselator error: %d\n", errno);
     46 }
     47 
     48 static void tessCbCombine(GLdouble coords[3], GLdouble *data[4], GLfloat weight[4], void **outData) {
     49     // let memory leak for now
     50     GLdouble *out = malloc(sizeof(GLdouble)*7); // x,y,z,r,g,b,a
     51     out[0] = coords[0];
     52     out[1] = coords[1];
     53     out[2] = coords[2];
     54     // color
     55     out[3] = weight[0]*data[0][3]+weight[1]*data[1][3]+weight[2]*data[2][3]+weight[3]*data[3][3];
     56     out[4] = weight[0]*data[0][4]+weight[1]*data[1][4]+weight[2]*data[2][4]+weight[3]*data[3][4];
     57     out[5] = weight[0]*data[0][5]+weight[1]*data[1][5]+weight[2]*data[2][5]+weight[3]*data[3][5];
     58     out[6] = weight[0]*data[0][6]+weight[1]*data[1][6]+weight[2]*data[2][6]+weight[3]*data[3][6];
     59     *outData = out;
     60 }
     61 
     62 //@todo move shaders to separate files
     63 static const GLchar *vertexSrc = "          \n\
     64 #version 420                                \n\
     65 in vec2 position;                           \n\
     66 in vec3 inColor;                            \n\
     67 out vec3 color;                             \n\
     68 void main() {                               \n\
     69     gl_Position = vec4(position, 0.0, 1.0); \n\
     70     color = inColor;                        \n\
     71 }                                           \n\
     72 ";
     73 
     74 static const GLchar *fragmentSrc = "    \n\
     75 #version 420                            \n\
     76 uniform double iTime;                   \n\
     77 in vec3 color;                          \n\
     78 out vec4 outColor;                      \n\
     79 void main() {                           \n\
     80     float c1 = abs(sin(float(iTime)));  \n\
     81     float c2 = abs(cos(float(iTime)));  \n\
     82     outColor = vec4(color+c1-c2, 1.0);  \n\
     83 }                                       \n\
     84 ";
     85 
     86 static GLuint mkShader(GLenum type, const GLchar *src) {
     87     GLuint shader = glCreateShader(type);
     88     glShaderSource(shader, 1, &src, NULL);
     89     glCompileShader(shader);
     90     GLint ok = 0;
     91     glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
     92     if (!ok) {
     93         static char buf[512] = {0};
     94         glGetShaderInfoLog(shader, sizeof(buf)-1, NULL, buf);
     95         fprintf(stderr, "Shader %d compile error: %s\n", (int)type, buf);
     96     }
     97     return shader;
     98 }
     99 
    100 static GLuint linkProgram(GLuint vertex, GLuint fragment) {
    101     GLuint shaderProgram = glCreateProgram();
    102     glAttachShader(shaderProgram, vertex);
    103     glAttachShader(shaderProgram, fragment);
    104     glBindAttribLocation(shaderProgram, 0, "position");
    105     glBindFragDataLocation(shaderProgram, 0, "outColor");
    106     glLinkProgram(shaderProgram);
    107     return shaderProgram;
    108 }
    109 
    110 void __attribute__((constructor)) start() {
    111     printf("start()\n");
    112     t_started = current_ts();
    113 }
    114 
    115 void __attribute((destructor)) end() {
    116     printf("end()\n");
    117 }
    118 
    119 int main(int argc, char *argv[]) {
    120     Display *dpy = XOpenDisplay(NULL);
    121     XSetWindowAttributes swa;
    122     Window win;
    123     XWindowAttributes gwa;
    124     XEvent xev;
    125     GLint attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
    126 
    127     if (dpy == NULL) {
    128         printf("\n\tcannot connect to X server\n\n");
    129         exit(0);
    130     }
    131 
    132     Window root = DefaultRootWindow(dpy);
    133     XVisualInfo *vi = glXChooseVisual(dpy, 0, attr);
    134 
    135     if (vi == NULL) {
    136         printf("\n\tno appropriate visual found\n\n");
    137         exit(0);
    138     } else {
    139         printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
    140     }
    141 
    142     Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
    143     swa.colormap = cmap;
    144     swa.event_mask = ExposureMask | KeyPressMask;
    145     win = XCreateWindow(dpy, root, 0, 0, 500, 500, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
    146     XMapWindow(dpy, win);
    147     XStoreName(dpy, win, "OPENGL");
    148     GLXContext ctx = glXCreateContext(dpy, vi, NULL, GL_TRUE);
    149     glXMakeCurrent(dpy, win, ctx);
    150 
    151     //GLdouble vertices_poly[][3] = { {-2,3,0}, {-2,0,0}, {2,0,0}, { 2,3,0}, {-1,2,0}, {-1,1,0}, {1,1,0}, { 1,2,0} };
    152     //GLdouble vertices_poly[][3] = { {-1,2,0}, {0,0,0}, {1,2,0}, {0,1.5,0} };
    153     /*GLdouble vertices_poly[][3] = {
    154         { -0.7, -0.5, 0.0 },
    155         { -0.3,  0.3, 0.0 },
    156         {  0.0,  0.6, 0.0 },
    157         {  0.4,  0.3, 0.0 },
    158         {  0.2, -0.4, 0.0 },
    159         {  0.7, -0.4, 0.0 },
    160         { -0.4, -0.7, 0.0 }
    161     };*/
    162     GLdouble vertices_poly[][6] = { { 0.0, 3.0, 0,  1, 0, 0},
    163                             {-1.0, 0.0, 0,  0, 1, 0},
    164                             { 1.6, 1.9, 0,  1, 0, 1},
    165                             {-1.6, 1.9, 0,  1, 1, 0},
    166                             { 1.0, 0.0, 0,  0, 0, 1} };
    167     int vertices_num = sizeof(vertices_poly)/sizeof(vertices_poly[0]);
    168     GLUtesselator *tess = gluNewTess();
    169     gluTessCallback(tess, GLU_TESS_BEGIN, (CALLBACK)tessCbBegin);
    170     gluTessCallback(tess, GLU_TESS_END, (CALLBACK)tessCbEnd);
    171     gluTessCallback(tess, GLU_TESS_VERTEX, (CALLBACK)tessCbVertex);
    172     gluTessCallback(tess, GLU_TESS_ERROR,  (CALLBACK)tessCbError);
    173     gluTessCallback(tess, GLU_TESS_COMBINE, (CALLBACK)tessCbCombine);
    174 
    175     GLuint vertex = mkShader(GL_VERTEX_SHADER, vertexSrc);
    176     GLuint fragment = mkShader(GL_FRAGMENT_SHADER, fragmentSrc);
    177     GLuint shaderPrg = linkProgram(vertex, fragment);
    178 
    179     while (1) {
    180         while (XPending(dpy)) {
    181             XEvent xev;
    182             XNextEvent(dpy, &xev);
    183             if (xev.type == Expose) {
    184                 XGetWindowAttributes(dpy, win, &gwa);
    185                 glViewport(0, 0, gwa.width, gwa.height);
    186             } else if (xev.type == KeyPress) {
    187                 printf("btn:%d\n", xev.xbutton.button);
    188                 if (xev.xbutton.button==24||xev.xbutton.button==9) {
    189                     glXMakeCurrent(dpy, None, NULL);
    190                     glXDestroyContext(dpy, ctx);
    191                     XDestroyWindow(dpy, win);
    192                     XCloseDisplay(dpy);
    193                     exit(0);
    194                 }
    195             } else if (xev.type == ConfigureNotify) {
    196                 XConfigureEvent *ce = (XConfigureEvent *)&xev;
    197                 glViewport(0, 0, ce->width, ce->height);
    198             }
    199         }
    200 
    201         // this scaling doesn't work for tesselation !!!
    202 
    203         /*glMatrixMode(GL_PROJECTION);
    204         glLoadIdentity();
    205         glOrtho(-10, 10, -10, 10, -1.5, 1.5);
    206         glMatrixMode(GL_MODELVIEW);
    207         glLoadIdentity();*/
    208 
    209         //glMatrixMode(GL_MODELVIEW);
    210         //glLoadIdentity();
    211         //glScaled(0.1, 0.1, 1.0);
    212 
    213         glClearColor(0.1f, 0.1f, 0.15f, 1.0f);
    214         glClear(GL_COLOR_BUFFER_BIT);
    215 
    216         GLfloat iTime = glGetUniformLocation(shaderPrg, "iTime");
    217         glUniform1d(iTime, current_ts()-t_started);
    218         //printf("%f\n", fabsf(sinf(current_ts()-t_started)));
    219 
    220         glUseProgram(shaderPrg);
    221 
    222         GLuint list = glGenLists(1);
    223         glNewList(list, GL_COMPILE);
    224         gluTessBeginPolygon(tess, NULL);
    225             gluTessBeginContour(tess);
    226                 for (int i=0;i<vertices_num;++i) {
    227                     gluTessVertex(tess, vertices_poly[i], vertices_poly[i]);
    228                 }
    229             gluTessEndContour(tess);
    230         gluTessEndPolygon(tess);
    231         glEndList();
    232 
    233         glCallList(list);
    234 
    235         glXSwapBuffers(dpy, win);
    236         usleep(1000*16);
    237     }
    238 }