opengl_x11

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

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 }