obj2d.c (8313B)
1 /* 2d object from single vertex */ 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 #define SIZE_W 800 16 #define SIZE_H 800 17 18 #define LEN(x) (sizeof(x)/sizeof(x[0])) 19 20 #define GL_CHECK(x) \ 21 x; \ 22 { \ 23 GLenum glError = glGetError(); \ 24 if (glError!=GL_NO_ERROR) { \ 25 printf("glGetError() = %i (%#.8x) at %s:%i\n", glError, glError, __FILE__, __LINE__); \ 26 exit(EXIT_FAILURE); \ 27 } \ 28 } 29 30 static double current_ts() { 31 struct timespec ts; 32 timespec_get(&ts, TIME_UTC); 33 return (double)ts.tv_sec + (double)ts.tv_nsec/1e9; 34 } 35 36 static double t_started; 37 38 static const GLchar *vertexSrc = R"( 39 #version 420 40 in vec2 position; 41 in vec3 color; 42 out vec3 dotColor; 43 void main() { 44 gl_Position = vec4(position, 0.0, 1.0); 45 dotColor = color; 46 } 47 )"; 48 49 static const GLchar *geometrySrc = R"( 50 #version 420 51 layout(points) in; 52 layout(line_strip,max_vertices=6) out; 53 in vec3 dotColor[]; 54 uniform double iTime; 55 out vec3 fColor; 56 57 mat2 rotate(float a) { 58 float s = sin(a); 59 float c = cos(a); 60 return mat2(c, -s, 61 s, c); 62 } 63 64 void main() { 65 fColor = dotColor[0]; 66 vec4 p = gl_in[0].gl_Position; 67 vec4 p1 = p+vec4(-0.1, -0.1, 0.0, 0.0); 68 p1 = vec4(p.xy+rotate(float(iTime))*(p1.xy - p.xy), 0.0, 1.0); 69 gl_Position = p1; 70 EmitVertex(); 71 gl_Position = p+vec4(0.1, -0.1, 0.0, 0.0); 72 gl_Position = vec4(p.xy+rotate(float(iTime))*(gl_Position.xy - p.xy), 0.0, 1.0); 73 EmitVertex(); 74 gl_Position = p+vec4(0.1, 0.1, 0.0, 0.0); 75 gl_Position = vec4(p.xy+rotate(float(iTime))*(gl_Position.xy - p.xy), 0.0, 1.0); 76 EmitVertex(); 77 gl_Position = p+vec4(-0.1, 0.1, 0.0, 0.0); 78 gl_Position = vec4(p.xy+rotate(float(iTime))*(gl_Position.xy - p.xy), 0.0, 1.0); 79 EmitVertex(); 80 gl_Position = p1; 81 EmitVertex(); 82 EndPrimitive(); 83 } 84 )"; 85 86 static const GLchar *fragmentSrc = R"( 87 #version 420 88 uniform double iTime; 89 in vec3 fColor; 90 out vec4 outColor; 91 void main() { 92 vec3 color = fColor; 93 if (gl_FragCoord.x < 300) { 94 color.g = 1.0f; 95 } 96 outColor = vec4(color, 1.0); 97 } 98 )"; 99 100 static GLuint mkShader(GLenum type, const GLchar *src) { 101 GLuint shader = glCreateShader(type); 102 glShaderSource(shader, 1, &src, NULL); 103 glCompileShader(shader); 104 GLint ok = 0; 105 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); 106 if (!ok) { 107 static char buf[512] = {0}; 108 glGetShaderInfoLog(shader, sizeof(buf)-1, NULL, buf); 109 fprintf(stderr, "Shader %d compile error: %s\n", (int)type, buf); 110 } 111 return shader; 112 } 113 114 static GLuint linkProgram(GLuint vertex, GLuint geometry, GLuint fragment) { 115 GLuint shaderProgram = glCreateProgram(); 116 glAttachShader(shaderProgram, vertex); 117 glAttachShader(shaderProgram, geometry); 118 glAttachShader(shaderProgram, fragment); 119 //glBindAttribLocation(shaderProgram, 0, "position"); 120 //glBindAttribLocation(shaderProgram, 1, "color"); 121 glLinkProgram(shaderProgram); 122 return shaderProgram; 123 } 124 125 void __attribute__((constructor)) start() { 126 printf("start()\n"); 127 t_started = current_ts(); 128 } 129 130 void __attribute((destructor)) end() { 131 printf("end()\n"); 132 } 133 134 struct vec2 { 135 float x; 136 float y; 137 }; 138 139 struct vec2 rand_shift(void) { 140 int xs = (rand()%2)==0?1:-1; 141 int ys = (rand()%2)==0?1:-1; 142 int x = xs*rand()%20; 143 int y = ys*rand()%20; 144 return (struct vec2){ .x=(float)x/10000.f, .y=(float)y/10000.f}; 145 } 146 147 int main(void) { 148 srand(time(0)); 149 Display *dpy = XOpenDisplay(NULL); 150 XSetWindowAttributes swa; 151 Window win; 152 XWindowAttributes gwa; 153 GLint attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; 154 155 if (dpy == NULL) { 156 printf("\n\tcannot connect to X server\n\n"); 157 exit(0); 158 } 159 160 Window root = DefaultRootWindow(dpy); 161 XVisualInfo *vi = glXChooseVisual(dpy, 0, attr); 162 163 if (vi == NULL) { 164 printf("\n\tno appropriate visual found\n\n"); 165 exit(0); 166 } else { 167 printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */ 168 } 169 170 Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone); 171 swa.colormap = cmap; 172 swa.event_mask = ExposureMask | KeyPressMask; 173 win = XCreateWindow(dpy, root, 0, 0, SIZE_W, SIZE_H, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa); 174 XMapWindow(dpy, win); 175 XStoreName(dpy, win, "OPENGL"); 176 GLXContext ctx = glXCreateContext(dpy, vi, NULL, GL_TRUE); 177 glXMakeCurrent(dpy, win, ctx); 178 179 // USEFUL DEBUG INFO 180 //@todo validate ASTC support 181 /*GLint extn; 182 GL_CHECK(glGetIntegerv(GL_NUM_EXTENSIONS, &extn)); 183 printf("%d GL Extensions:\n", extn); 184 for (GLint i=0; i<extn; ++i) { 185 printf("\t%s\n", glGetStringi(GL_EXTENSIONS, i)); 186 }*/ 187 188 GLuint vao; 189 glGenVertexArrays(1, &vao); 190 glBindVertexArray(vao); 191 192 // x,y, color(r,g,b) 193 GLfloat vertices[][5] = { 194 {-0.3, -0.5, 1.f, 0.f, 0.f}, 195 { 0.6, -0.1, 0.f, 1.f, 0.f}, 196 { 0.4, 0.4, 0.f, 0.f, 1.f}, 197 {-0.5, 0.6, 1.f, 1.f, 0.f} 198 }; 199 200 GLuint vbo; 201 glGenBuffers(1, &vbo); 202 glBindBuffer(GL_ARRAY_BUFFER, vbo); 203 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); 204 205 GLuint vertex = mkShader(GL_VERTEX_SHADER, vertexSrc); 206 GLuint geometry = mkShader(GL_GEOMETRY_SHADER, geometrySrc); 207 GLuint fragment = mkShader(GL_FRAGMENT_SHADER, fragmentSrc); 208 GLuint shaderPrg = linkProgram(vertex, geometry, fragment); 209 210 GLint prgStatus; 211 glGetProgramiv(shaderPrg, GL_LINK_STATUS, &prgStatus); 212 printf("shader link status: %s\n", prgStatus == GL_TRUE ? "ok" : "error"); 213 214 GLint position = glGetAttribLocation(shaderPrg, "position"); 215 glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void *)0); 216 glEnableVertexAttribArray(position); 217 GLint color = glGetAttribLocation(shaderPrg, "color"); 218 glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(2*sizeof(GLfloat))); 219 glEnableVertexAttribArray(color); 220 221 glLineWidth(1.f); 222 glPointSize(4.f); 223 224 while (1) { 225 while (XPending(dpy)) { 226 XEvent xev; 227 XNextEvent(dpy, &xev); 228 if (xev.type == Expose) { 229 XGetWindowAttributes(dpy, win, &gwa); 230 glViewport(0, 0, gwa.width, gwa.height); 231 } else if (xev.type == KeyPress) { 232 printf("btn:%3d\n", xev.xbutton.button); 233 if (xev.xbutton.button==24||xev.xbutton.button==9) { 234 glXMakeCurrent(dpy, None, NULL); 235 glXDestroyContext(dpy, ctx); 236 XDestroyWindow(dpy, win); 237 XCloseDisplay(dpy); 238 exit(0); 239 } 240 } else if (xev.type == ConfigureNotify) { 241 XConfigureEvent *ce = (XConfigureEvent *)&xev; 242 glViewport(0, 0, ce->width, ce->height); 243 } 244 } 245 for (size_t i=0;i<LEN(vertices);++i) { 246 struct vec2 shift = rand_shift(); 247 vertices[i][0] += shift.x; 248 vertices[i][1] += shift.y; 249 } 250 glNamedBufferData(vbo, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); 251 252 glClearColor(0.1f, 0.1f, 0.15f, 1.0f); 253 glClear(GL_COLOR_BUFFER_BIT); 254 255 GLfloat iTime = glGetUniformLocation(shaderPrg, "iTime"); 256 glUniform1d(iTime, current_ts()-t_started); 257 //printf("%f\n", fabsf(sinf(current_ts()-t_started))); 258 259 glUseProgram(shaderPrg); 260 glDrawArrays(GL_POINTS, 0, LEN(vertices)); 261 262 glXSwapBuffers(dpy, win); 263 usleep(1000*7); // 144hz 264 } 265 }