opengl_x11

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

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 }