opengl_x11

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

trans.c (9760B)


      1 /* transformation matrices */
      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 #include "../cglm/include/cglm/cglm.h"
     15 #define STB_IMAGE_IMPLEMENTATION
     16 #include "stb_image.h"
     17 #include "astc.h"
     18 
     19 #define GL_CHECK(x)                                                                           \
     20 x;                                                                                            \
     21 {                                                                                             \
     22     GLenum glError = glGetError();                                                            \
     23     if (glError!=GL_NO_ERROR) {                                                               \
     24         printf("glGetError() = %i (%#.8x) at %s:%i\n", glError, glError, __FILE__, __LINE__); \
     25         exit(EXIT_FAILURE);                                                                   \
     26     }                                                                                         \
     27 }
     28 
     29 static const double current_ts() {
     30     struct timespec ts;
     31     timespec_get(&ts, TIME_UTC);
     32     return (double)ts.tv_sec + (double)ts.tv_nsec/1e9;
     33 }
     34 
     35 static double t_started;
     36 
     37 //@todo move shaders to separate files
     38 static const GLchar *vertexSrc = R"(
     39 #version 420
     40 layout(location=0) in vec2 position;
     41 layout(location=1) in vec2 aTexCoord;
     42 out vec2 texCoord;
     43 uniform mat4 trans;
     44 void main() {
     45     mat4 t;
     46     t[0][0]=1.0f;
     47     t[1][1]=1.0f;
     48     t[2][2]=1.0f;
     49     t[3][3]=1.0f;
     50     gl_Position = trans * vec4(position, 0.0, 1.0);
     51     texCoord = aTexCoord;
     52 }
     53 )";
     54 
     55 static const GLchar *fragmentSrc = R"(
     56 #version 420
     57 uniform double iTime;
     58 uniform sampler2D ourTex;
     59 uniform mat4 trans;
     60 out vec4 outColor;
     61 in vec2 texCoord;
     62 void main() {
     63     vec3 color;
     64     color.r = 0.2;
     65     color.g = 0.6;
     66     color.b = 0.1;
     67     float c1 = abs(sin(float(iTime)));
     68     float c2 = abs(cos(float(iTime)));
     69     vec4 modColor = vec4(color+c1-c2, 1.0);
     70     outColor = texture(ourTex, texCoord) + modColor;
     71 }
     72 )";
     73 
     74 static GLuint mkShader(GLenum type, const GLchar *src) {
     75     GLuint shader = glCreateShader(type);
     76     glShaderSource(shader, 1, &src, NULL);
     77     glCompileShader(shader);
     78     GLint ok = 0;
     79     glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
     80     if (!ok) {
     81         static char buf[512] = {0};
     82         glGetShaderInfoLog(shader, sizeof(buf)-1, NULL, buf);
     83         fprintf(stderr, "Shader %d compile error: %s\n", (int)type, buf);
     84     }
     85     return shader;
     86 }
     87 
     88 static GLuint linkProgram(GLuint vertex, GLuint fragment) {
     89     GLuint shaderProgram = glCreateProgram();
     90     glAttachShader(shaderProgram, vertex);
     91     glAttachShader(shaderProgram, fragment);
     92     glBindAttribLocation(shaderProgram, 0, "position");
     93     glBindAttribLocation(shaderProgram, 1, "aTexCoord");
     94     glLinkProgram(shaderProgram);
     95     return shaderProgram;
     96 }
     97 
     98 static GLuint mkTexture(const char *filename) {
     99     GLuint tex;
    100     glGenTextures(1, &tex);
    101     glBindTexture(GL_TEXTURE_2D, tex);
    102     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    103     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    104     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    105     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    106     int w, h, numchan;
    107     //stbi_set_flip_vertically_on_load(1);
    108     uint8_t *data = stbi_load(filename, &w, &h, &numchan, 3);
    109     if (data) {
    110         printf("texture %dx%d %dbpp\n", w, h, numchan*8);
    111         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    112         glGenerateMipmap(GL_TEXTURE_2D);
    113         glEnable(GL_TEXTURE_2D);
    114         stbi_image_free(data);
    115     } else {
    116         printf("Failed to load texture %s: %s\n", filename, stbi_failure_reason());
    117     }
    118     return tex;
    119 }
    120 
    121 void __attribute__((constructor)) start() {
    122     printf("start()\n");
    123 
    124     // just a playground
    125     vec4 vector = {1.0f, 0.0f, 0.0f, 1.0f};
    126     mat4 trans;
    127     glm_mat4_identity(trans);
    128     vec3 t = {1.0f, 1.0f, 0.0f};
    129     glm_translate(trans, t);
    130     vec4 out;
    131     glm_mat4_mulv(trans, vector, out);
    132     glm_vec4_print(out, stdout);
    133 
    134     mat4 trans1;
    135     glm_mat4_identity(trans1);
    136     glm_rotate(trans1, glm_rad(90.0f), (vec3){0.0, 0.0, 1.0});
    137     glm_scale(trans1, (vec3){0.5, 0.5, 0.5});
    138     glm_mat4_print(trans1, stdout);
    139 
    140     t_started = current_ts();
    141 }
    142 
    143 void __attribute((destructor)) end() {
    144     printf("end()\n");
    145 }
    146 
    147 int main(int argc, char *argv[]) {
    148     const char *tex_fname;
    149     bool is_astc = false;
    150     if (argc>1) {
    151         tex_fname = argv[1];
    152         int len = strlen(tex_fname);
    153         // ".astc" extension = 5 bytes
    154         is_astc = (len>ASTC_LEN&&strncmp(tex_fname+len-ASTC_LEN, ASTC_EXT, ASTC_LEN)==0);
    155     } else {
    156         tex_fname = "hina.astc";
    157         is_astc = true;
    158     }
    159     printf("texture file: %s (%s)\n", tex_fname, is_astc ? "astc" : "plain");
    160 
    161     Display *dpy = XOpenDisplay(NULL);
    162     XSetWindowAttributes swa;
    163     Window win;
    164     XWindowAttributes gwa;
    165     GLint attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
    166 
    167     if (dpy == NULL) {
    168         printf("\n\tcannot connect to X server\n\n");
    169         exit(0);
    170     }
    171 
    172     Window root = DefaultRootWindow(dpy);
    173     XVisualInfo *vi = glXChooseVisual(dpy, 0, attr);
    174 
    175     if (vi == NULL) {
    176         printf("\n\tno appropriate visual found\n\n");
    177         exit(0);
    178     } else {
    179         printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
    180     }
    181 
    182     Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
    183     swa.colormap = cmap;
    184     swa.event_mask = ExposureMask | KeyPressMask;
    185     win = XCreateWindow(dpy, root, 0, 0, 500, 500, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
    186     XMapWindow(dpy, win);
    187     XStoreName(dpy, win, "OPENGL");
    188     GLXContext ctx = glXCreateContext(dpy, vi, NULL, GL_TRUE);
    189     glXMakeCurrent(dpy, win, ctx);
    190 
    191     // USEFUL DEBUG INFO
    192     //@todo validate ASTC support
    193     /*GLint extn;
    194     GL_CHECK(glGetIntegerv(GL_NUM_EXTENSIONS, &extn));
    195     printf("%d GL Extensions:\n", extn);
    196     for (GLint i=0; i<extn; ++i) {
    197         printf("\t%s\n", glGetStringi(GL_EXTENSIONS, i));
    198     }*/
    199 
    200     GLuint vao;
    201     glGenVertexArrays(1, &vao);
    202     glBindVertexArray(vao);
    203 
    204     // @todo geh
    205     const GLfloat c = 0; //0.099f;
    206 
    207     // x,y,tx,ty
    208     static const GLfloat vertices[] = {
    209         -0.5, -0.5, 0+c, 1-c,
    210          0.5, -0.5, 1-c, 1-c,
    211          0.5,  0.5, 1-c, 0+c,
    212         -0.5,  0.5, 0+c, 0+c
    213     };
    214     static const GLuint elements[] = {
    215         0, 1, 2,
    216         2, 3, 0
    217     };
    218 
    219     GLuint vbo;
    220     glGenBuffers(1, &vbo);
    221     glBindBuffer(GL_ARRAY_BUFFER, vbo);
    222     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    223 
    224     GLuint ebo;
    225     glGenBuffers(1, &ebo);
    226     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    227     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
    228 
    229     GLuint vertex = mkShader(GL_VERTEX_SHADER, vertexSrc);
    230     GLuint fragment = mkShader(GL_FRAGMENT_SHADER, fragmentSrc);
    231     GLuint shaderPrg = linkProgram(vertex, fragment);
    232 
    233     GLint prgStatus;
    234     glGetProgramiv(shaderPrg, GL_LINK_STATUS, &prgStatus);
    235     printf("shader link status: %s\n", prgStatus == GL_TRUE ? "ok" : "error");
    236 
    237     // texture
    238     GLuint tex = is_astc ? mkTextureAstc(tex_fname) : mkTexture(tex_fname);
    239     GLint position = glGetAttribLocation(shaderPrg, "position");
    240     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void *)0);
    241     glEnableVertexAttribArray(position);
    242     GLint aTexCoord = glGetAttribLocation(shaderPrg, "aTexCoord");
    243     glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void *)(2*sizeof(GLfloat)));
    244     glEnableVertexAttribArray(aTexCoord);
    245 
    246     mat4 trans;
    247     glm_mat4_identity(trans);
    248     //glm_rotate(trans, glm_rad(90.0f), (vec3){0.0, 0.0, 1.0});
    249     glm_scale(trans, (vec3){1.2, 1.2, 1.2});
    250     glm_mat4_print(trans, stdout);
    251 
    252     float rotation = 1.f;
    253 
    254     while (1) {
    255         while (XPending(dpy)) {
    256             XEvent xev;
    257             XNextEvent(dpy, &xev);
    258             if (xev.type == Expose) {
    259                 XGetWindowAttributes(dpy, win, &gwa);
    260                 glViewport(0, 0, gwa.width, gwa.height);
    261             } else if (xev.type == KeyPress) {
    262                 printf("btn:%3d\n", xev.xbutton.button);
    263                 if (xev.xbutton.button==24||xev.xbutton.button==9) {
    264                     glXMakeCurrent(dpy, None, NULL);
    265                     glXDestroyContext(dpy, ctx);
    266                     XDestroyWindow(dpy, win);
    267                     XCloseDisplay(dpy);
    268                     exit(0);
    269                 }
    270             } else if (xev.type == ConfigureNotify) {
    271                 XConfigureEvent *ce = (XConfigureEvent *)&xev;
    272                 glViewport(0, 0, ce->width, ce->height);
    273             }
    274         }
    275 
    276         glClearColor(0.1f, 0.1f, 0.15f, 1.0f);
    277         glClear(GL_COLOR_BUFFER_BIT);
    278 
    279         GLfloat iTime = glGetUniformLocation(shaderPrg, "iTime");
    280         glUniform1d(iTime, current_ts()-t_started);
    281         //printf("%f\n", fabsf(sinf(current_ts()-t_started)));
    282 
    283         glm_rotate(trans, glm_rad(rotation), (vec3){0.0, 0.0, 1.0});
    284         GLuint transform = glGetUniformLocation(shaderPrg, "trans");
    285         glUniformMatrix4fv(transform, 1, GL_FALSE, trans[0]);
    286 
    287         glUseProgram(shaderPrg);
    288 
    289         glUniform1i(tex, 0);
    290         glActiveTexture(GL_TEXTURE0);
    291         glBindTexture(GL_TEXTURE_2D, tex);
    292         glDrawElements(GL_TRIANGLES, sizeof(elements)/sizeof(elements[0]), GL_UNSIGNED_INT, 0);
    293 
    294         glXSwapBuffers(dpy, win);
    295         usleep(1000*7); // 144hz
    296     }
    297 }