opengl_x11

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

tesselating.c (7778B)


      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 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 = R"(
     64 #version 420
     65 in vec2 position;
     66 in vec3 inColor;
     67 out vec3 color;
     68 void main() {
     69     gl_Position = vec4(position, 0.0, 1.0);
     70     color = inColor;
     71 }
     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(void) {
    120     Display *dpy = XOpenDisplay(NULL);
    121     XSetWindowAttributes swa;
    122     Window win;
    123     XWindowAttributes gwa;
    124     GLint attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
    125 
    126     if (dpy == NULL) {
    127         printf("\n\tcannot connect to X server\n\n");
    128         exit(0);
    129     }
    130 
    131     Window root = DefaultRootWindow(dpy);
    132     XVisualInfo *vi = glXChooseVisual(dpy, 0, attr);
    133 
    134     if (vi == NULL) {
    135         printf("\n\tno appropriate visual found\n\n");
    136         exit(0);
    137     } else {
    138         printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
    139     }
    140 
    141     Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
    142     swa.colormap = cmap;
    143     swa.event_mask = ExposureMask | KeyPressMask;
    144     win = XCreateWindow(dpy, root, 0, 0, 500, 500, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
    145     XMapWindow(dpy, win);
    146     XStoreName(dpy, win, "OPENGL");
    147     GLXContext ctx = glXCreateContext(dpy, vi, NULL, GL_TRUE);
    148     glXMakeCurrent(dpy, win, ctx);
    149 
    150     //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} };
    151     //GLdouble vertices_poly[][3] = { {-1,2,0}, {0,0,0}, {1,2,0}, {0,1.5,0} };
    152     /*GLdouble vertices_poly[][3] = {
    153         { -0.7, -0.5, 0.0 },
    154         { -0.3,  0.3, 0.0 },
    155         {  0.0,  0.6, 0.0 },
    156         {  0.4,  0.3, 0.0 },
    157         {  0.2, -0.4, 0.0 },
    158         {  0.7, -0.4, 0.0 },
    159         { -0.4, -0.7, 0.0 }
    160     };*/
    161     GLdouble vertices_poly[][6] = { { 0.0, 3.0, 0,  1, 0, 0},
    162                             {-1.0, 0.0, 0,  0, 1, 0},
    163                             { 1.6, 1.9, 0,  1, 0, 1},
    164                             {-1.6, 1.9, 0,  1, 1, 0},
    165                             { 1.0, 0.0, 0,  0, 0, 1} };
    166     int vertices_num = sizeof(vertices_poly)/sizeof(vertices_poly[0]);
    167     GLUtesselator *tess = gluNewTess();
    168     gluTessCallback(tess, GLU_TESS_BEGIN, (CALLBACK)tessCbBegin);
    169     gluTessCallback(tess, GLU_TESS_END, (CALLBACK)tessCbEnd);
    170     gluTessCallback(tess, GLU_TESS_VERTEX, (CALLBACK)tessCbVertex);
    171     gluTessCallback(tess, GLU_TESS_ERROR,  (CALLBACK)tessCbError);
    172     gluTessCallback(tess, GLU_TESS_COMBINE, (CALLBACK)tessCbCombine);
    173 
    174     GLuint vertex = mkShader(GL_VERTEX_SHADER, vertexSrc);
    175     GLuint fragment = mkShader(GL_FRAGMENT_SHADER, fragmentSrc);
    176     GLuint shaderPrg = linkProgram(vertex, fragment);
    177 
    178     while (1) {
    179         while (XPending(dpy)) {
    180             XEvent xev;
    181             XNextEvent(dpy, &xev);
    182             if (xev.type == Expose) {
    183                 XGetWindowAttributes(dpy, win, &gwa);
    184                 glViewport(0, 0, gwa.width, gwa.height);
    185             } else if (xev.type == KeyPress) {
    186                 printf("btn:%d\n", xev.xbutton.button);
    187                 if (xev.xbutton.button==24||xev.xbutton.button==9) {
    188                     glXMakeCurrent(dpy, None, NULL);
    189                     glXDestroyContext(dpy, ctx);
    190                     XDestroyWindow(dpy, win);
    191                     XCloseDisplay(dpy);
    192                     exit(0);
    193                 }
    194             } else if (xev.type == ConfigureNotify) {
    195                 XConfigureEvent *ce = (XConfigureEvent *)&xev;
    196                 glViewport(0, 0, ce->width, ce->height);
    197             }
    198         }
    199 
    200         // this scaling doesn't work for tesselation !!!
    201 
    202         /*glMatrixMode(GL_PROJECTION);
    203         glLoadIdentity();
    204         glOrtho(-10, 10, -10, 10, -1.5, 1.5);
    205         glMatrixMode(GL_MODELVIEW);
    206         glLoadIdentity();*/
    207 
    208         //glMatrixMode(GL_MODELVIEW);
    209         //glLoadIdentity();
    210         //glScaled(0.1, 0.1, 1.0);
    211 
    212         glClearColor(0.1f, 0.1f, 0.15f, 1.0f);
    213         glClear(GL_COLOR_BUFFER_BIT);
    214 
    215         GLfloat iTime = glGetUniformLocation(shaderPrg, "iTime");
    216         glUniform1d(iTime, current_ts()-t_started);
    217         //printf("%f\n", fabsf(sinf(current_ts()-t_started)));
    218 
    219         glUseProgram(shaderPrg);
    220         //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    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 }