obj2d.c (7438B)
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 const 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 out vec3 fColor; 55 void main() { 56 fColor = dotColor[0]; 57 vec4 p = gl_in[0].gl_Position; 58 gl_Position = p+vec4(-0.1, -0.1, 0.0, 0.0); 59 EmitVertex(); 60 gl_Position = p+vec4(0.1, -0.1, 0.0, 0.0); 61 EmitVertex(); 62 gl_Position = p+vec4(0.1, 0.1, 0.0, 0.0); 63 EmitVertex(); 64 gl_Position = p+vec4(-0.1, 0.1, 0.0, 0.0); 65 EmitVertex(); 66 gl_Position = p+vec4(-0.1, -0.1, 0.0, 0.0); 67 EmitVertex(); 68 EndPrimitive(); 69 } 70 )"; 71 72 static const GLchar *fragmentSrc = R"( 73 #version 420 74 uniform double iTime; 75 in vec3 fColor; 76 out vec4 outColor; 77 void main() { 78 vec3 color = fColor; 79 if (gl_FragCoord.x < 300) { 80 color.g = 1.0f; 81 } 82 outColor = vec4(color, 1.0); 83 } 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 geometry, GLuint fragment) { 101 GLuint shaderProgram = glCreateProgram(); 102 glAttachShader(shaderProgram, vertex); 103 glAttachShader(shaderProgram, geometry); 104 glAttachShader(shaderProgram, fragment); 105 //glBindAttribLocation(shaderProgram, 0, "position"); 106 //glBindAttribLocation(shaderProgram, 1, "color"); 107 glLinkProgram(shaderProgram); 108 return shaderProgram; 109 } 110 111 void __attribute__((constructor)) start() { 112 printf("start()\n"); 113 t_started = current_ts(); 114 } 115 116 void __attribute((destructor)) end() { 117 printf("end()\n"); 118 } 119 120 int main(int argc, char *argv[]) { 121 Display *dpy = XOpenDisplay(NULL); 122 XSetWindowAttributes swa; 123 Window win; 124 XWindowAttributes gwa; 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, SIZE_W, SIZE_H, 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 // USEFUL DEBUG INFO 152 //@todo validate ASTC support 153 /*GLint extn; 154 GL_CHECK(glGetIntegerv(GL_NUM_EXTENSIONS, &extn)); 155 printf("%d GL Extensions:\n", extn); 156 for (GLint i=0; i<extn; ++i) { 157 printf("\t%s\n", glGetStringi(GL_EXTENSIONS, i)); 158 }*/ 159 160 GLuint vao; 161 glGenVertexArrays(1, &vao); 162 glBindVertexArray(vao); 163 164 // x,y, color(r,g,b) 165 GLfloat vertices[][5] = { 166 {-0.3, -0.5, 1.f, 0.f, 0.f}, 167 { 0.6, -0.1, 0.f, 1.f, 0.f}, 168 { 0.4, 0.4, 0.f, 0.f, 1.f}, 169 {-0.5, 0.6, 1.f, 1.f, 0.f} 170 }; 171 172 GLuint vbo; 173 glGenBuffers(1, &vbo); 174 glBindBuffer(GL_ARRAY_BUFFER, vbo); 175 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); 176 177 GLuint vertex = mkShader(GL_VERTEX_SHADER, vertexSrc); 178 GLuint geometry = mkShader(GL_GEOMETRY_SHADER, geometrySrc); 179 GLuint fragment = mkShader(GL_FRAGMENT_SHADER, fragmentSrc); 180 GLuint shaderPrg = linkProgram(vertex, geometry, fragment); 181 182 GLint prgStatus; 183 glGetProgramiv(shaderPrg, GL_LINK_STATUS, &prgStatus); 184 printf("shader link status: %s\n", prgStatus == GL_TRUE ? "ok" : "error"); 185 186 GLint position = glGetAttribLocation(shaderPrg, "position"); 187 glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void *)0); 188 glEnableVertexAttribArray(position); 189 GLint color = glGetAttribLocation(shaderPrg, "color"); 190 glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(2*sizeof(GLfloat))); 191 glEnableVertexAttribArray(color); 192 193 glLineWidth(1.f); 194 glPointSize(4.f); 195 196 while (1) { 197 while (XPending(dpy)) { 198 XEvent xev; 199 XNextEvent(dpy, &xev); 200 if (xev.type == Expose) { 201 XGetWindowAttributes(dpy, win, &gwa); 202 glViewport(0, 0, gwa.width, gwa.height); 203 } else if (xev.type == KeyPress) { 204 printf("btn:%3d\n", xev.xbutton.button); 205 if (xev.xbutton.button==24||xev.xbutton.button==9) { 206 glXMakeCurrent(dpy, None, NULL); 207 glXDestroyContext(dpy, ctx); 208 XDestroyWindow(dpy, win); 209 XCloseDisplay(dpy); 210 exit(0); 211 } 212 } else if (xev.type == ConfigureNotify) { 213 XConfigureEvent *ce = (XConfigureEvent *)&xev; 214 glViewport(0, 0, ce->width, ce->height); 215 } 216 } 217 vertices[0][0] += 0.0003f; 218 glNamedBufferData(vbo, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); 219 220 221 glClearColor(0.1f, 0.1f, 0.15f, 1.0f); 222 glClear(GL_COLOR_BUFFER_BIT); 223 224 GLfloat iTime = glGetUniformLocation(shaderPrg, "iTime"); 225 glUniform1d(iTime, current_ts()-t_started); 226 //printf("%f\n", fabsf(sinf(current_ts()-t_started))); 227 228 glUseProgram(shaderPrg); 229 glDrawArrays(GL_POINTS, 0, LEN(vertices)); 230 231 glXSwapBuffers(dpy, win); 232 usleep(1000*7); // 144hz 233 } 234 }