shaders.c (6061B)
1 /* basic vertex+fragment shaders */ 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 Display *dpy; 16 Window root; 17 GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; 18 XVisualInfo *vi; 19 XSetWindowAttributes swa; 20 Window win; 21 XWindowAttributes gwa; 22 XEvent xev; 23 24 static const double current_ts() { 25 struct timespec ts; 26 timespec_get(&ts, TIME_UTC); 27 return (double)ts.tv_sec + (double)ts.tv_nsec/1e9; 28 } 29 30 static double t_started; 31 32 //@todo move shaders to separate files 33 static const GLchar *vertexSrc = R"( 34 #version 420 35 in vec2 position; 36 in vec3 inColor; 37 out vec3 color; 38 void main() { 39 gl_Position = vec4(position, 0.0, 1.0); 40 color = inColor; 41 } 42 )"; 43 44 static const GLchar *fragmentSrc = R"( 45 #version 420 46 uniform double iTime; 47 in vec3 color; 48 out vec4 outColor; 49 void main() { 50 float c1 = abs(sin(float(iTime))); 51 float c2 = abs(cos(float(iTime))); 52 outColor = vec4(color+c1-c2, 1.0); 53 } 54 )"; 55 56 static GLuint mkShader(GLenum type, const GLchar *src) { 57 GLuint shader = glCreateShader(type); 58 glShaderSource(shader, 1, &src, NULL); 59 glCompileShader(shader); 60 GLint ok = 0; 61 glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); 62 if (!ok) { 63 static char buf[512] = {0}; 64 glGetShaderInfoLog(shader, sizeof(buf)-1, NULL, buf); 65 fprintf(stderr, "Shader %d compile error: %s\n", (int)type, buf); 66 } 67 return shader; 68 } 69 70 static GLuint linkProgram(GLuint vertex, GLuint fragment) { 71 GLuint shaderProgram = glCreateProgram(); 72 glAttachShader(shaderProgram, vertex); 73 glAttachShader(shaderProgram, fragment); 74 glBindAttribLocation(shaderProgram, 0, "position"); 75 glBindFragDataLocation(shaderProgram, 0, "outColor"); 76 glLinkProgram(shaderProgram); 77 return shaderProgram; 78 } 79 80 void __attribute__((constructor)) start() { 81 printf("start()\n"); 82 t_started = current_ts(); 83 } 84 85 void __attribute((destructor)) end() { 86 printf("end()\n"); 87 } 88 89 int main(int argc, char *argv[]) { 90 dpy = XOpenDisplay(NULL); 91 92 if (dpy == NULL) { 93 printf("\n\tcannot connect to X server\n\n"); 94 exit(0); 95 } 96 97 root = DefaultRootWindow(dpy); 98 vi = glXChooseVisual(dpy, 0, att); 99 100 if (vi == NULL) { 101 printf("\n\tno appropriate visual found\n\n"); 102 exit(0); 103 } else { 104 printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */ 105 } 106 107 Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone); 108 swa.colormap = cmap; 109 swa.event_mask = ExposureMask | KeyPressMask; 110 win = XCreateWindow(dpy, root, 0, 0, 500, 500, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa); 111 XMapWindow(dpy, win); 112 XStoreName(dpy, win, "OPENGL"); 113 GLXContext ctx = glXCreateContext(dpy, vi, NULL, GL_TRUE); 114 glXMakeCurrent(dpy, win, ctx); 115 116 GLuint vao; 117 glGenVertexArrays(1, &vao); 118 glBindVertexArray(vao); 119 120 // [x, y, r, g, b] 121 static const GLfloat vertices[] = { 122 0.01f, 0.01f, 1.0f, 0.0f, 0.0f, 123 0.8f, 0.0f, 0.0f, 1.0f, 0.0f, 124 0.0f, 0.8f, 0.0f, 0.0f, 1.0f, 125 126 -0.01f, -0.01f, 0.0f, 0.0f, 1.0f, 127 -0.8f, 0.0f, 0.0f, 1.0f, 0.0f, 128 0.0f, -0.8f, 1.0f, 0.0f, 0.0f, 129 130 0.3f, 0.3f, 1.0f, 0.0f, 0.0f, 131 0.3f, 0.6f, 1.0f, 0.0f, 0.0f, 132 0.6f, 0.3f, 1.0f, 0.0f, 0.0f, 133 0.6f, 0.6f, 1.0f, 0.0f, 0.0f 134 }; 135 136 static const GLuint elements[] = { 137 0, 1, 5, 138 3, 2, 4, 139 6, 7, 8, 140 7, 8, 9 141 }; 142 143 GLuint vbo; 144 glGenBuffers(1, &vbo); 145 glBindBuffer(GL_ARRAY_BUFFER, vbo); 146 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 147 148 GLuint ebo; 149 glGenBuffers(1, &ebo); 150 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 151 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW); 152 153 GLuint vertex = mkShader(GL_VERTEX_SHADER, vertexSrc); 154 GLuint fragment = mkShader(GL_FRAGMENT_SHADER, fragmentSrc); 155 GLuint shaderPrg = linkProgram(vertex, fragment); 156 157 while (1) { 158 while (XPending(dpy)) { 159 XEvent xev; 160 XNextEvent(dpy, &xev); 161 if (xev.type == Expose) { 162 XGetWindowAttributes(dpy, win, &gwa); 163 glViewport(0, 0, gwa.width, gwa.height); 164 } else if (xev.type == KeyPress) { 165 printf("btn:%d\n", xev.xbutton.button); 166 if (xev.xbutton.button==24||xev.xbutton.button==9) { 167 glXMakeCurrent(dpy, None, NULL); 168 glXDestroyContext(dpy, ctx); 169 XDestroyWindow(dpy, win); 170 XCloseDisplay(dpy); 171 exit(0); 172 } 173 } else if (xev.type == ConfigureNotify) { 174 XConfigureEvent *ce = (XConfigureEvent *)&xev; 175 glViewport(0, 0, ce->width, ce->height); 176 } 177 } 178 179 glClearColor(0.1f, 0.1f, 0.15f, 1.0f); 180 glClear(GL_COLOR_BUFFER_BIT); 181 182 GLfloat iTime = glGetUniformLocation(shaderPrg, "iTime"); 183 glUniform1d(iTime, current_ts()-t_started); 184 //printf("%f\n", fabsf(sinf(current_ts()-t_started))); 185 186 glUseProgram(shaderPrg); 187 188 GLint position = glGetAttribLocation(shaderPrg, "position"); 189 glEnableVertexAttribArray(position); 190 glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), 0); 191 GLint color = glGetAttribLocation(shaderPrg, "inColor"); 192 glEnableVertexAttribArray(color); 193 glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void *)(2*sizeof(GLfloat))); 194 glDrawElements(GL_TRIANGLES, sizeof(elements), GL_UNSIGNED_INT, 0); 195 196 glXSwapBuffers(dpy, win); 197 usleep(1000*16); 198 } 199 }