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 }