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 }