diff options
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | assets/fragment.glsl | 6 | ||||
-rw-r--r-- | assets/vertex.glsl | 24 | ||||
m--------- | linmath.h | 0 | ||||
-rw-r--r-- | meson.build | 5 | ||||
-rw-r--r-- | src/hacks.h | 81 | ||||
-rw-r--r-- | src/main.c | 149 |
7 files changed, 243 insertions, 25 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1d0fe9b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "linmath.h"] + path = linmath.h + url = https://github.com/datenwolf/linmath.h diff --git a/assets/fragment.glsl b/assets/fragment.glsl index d6a6b52..a189112 100644 --- a/assets/fragment.glsl +++ b/assets/fragment.glsl @@ -1,12 +1,12 @@ #version 430 core -in vec2 texCoords; +in vec2 fTexCoords; -out vec4 outColor; +out vec4 oColor; uniform sampler2D texture0; void main() { - outColor = texture(texture0, texCoords); + oColor = texture(texture0, fTexCoords); } diff --git a/assets/vertex.glsl b/assets/vertex.glsl index 15140cf..ec8c0b6 100644 --- a/assets/vertex.glsl +++ b/assets/vertex.glsl @@ -1,11 +1,27 @@ #version 430 core -layout(location = 0) in vec2 vertexPosition; +layout(location = 0) in vec4 vPos; +layout(location = 1) in vec2 vTexCoord; +//layout(location = 1) in vec3 vNormal; -out vec2 texCoords; +//out vec3 fPos; +//out vec3 fNormal; +out vec2 fTexCoords; + +uniform mat4 model; +uniform mat4 viewProj; + +/* +uniform mat4 viewProj; +uniform mat3 normalTransform;*/ void main() { - gl_Position = vec4(vertexPosition, 0.0, 1.0); - texCoords = vertexPosition + vec2(0.5); + vec4 pos = vPos; + pos = model * pos; + pos.w = pos.w + 2.0; + gl_Position = viewProj * (pos / pos.w); + + //gl_Position = viewProj * model * vec4(vPos.xyz, 1.0); + fTexCoords = vTexCoord; } diff --git a/linmath.h b/linmath.h new file mode 160000 +Subproject 3eef82841046507e16a0f6194a61cee2eadd34b diff --git a/meson.build b/meson.build index 96ed03b..a9e41c6 100644 --- a/meson.build +++ b/meson.build @@ -2,9 +2,12 @@ project('juxtapos', 'c', default_options: ['warning_level=2']) add_project_arguments('-DGLEW_NO_GLU', language: 'c') +cc = meson.get_compiler('c') + gl = dependency('gl') glfw = dependency('glfw3') glew = dependency('glew') +m = cc.find_library('m', required: false) embed = generator(find_program('python3'), output: '@PLAINNAME@.h', @@ -23,7 +26,7 @@ juxtapos = executable('juxtapos', 'assets/fragment.glsl', ]), ], - dependencies: [glfw, glew], + dependencies: [glfw, glew, m], install: true, ) diff --git a/src/hacks.h b/src/hacks.h new file mode 100644 index 0000000..4846fd1 --- /dev/null +++ b/src/hacks.h @@ -0,0 +1,81 @@ +#define NONE(...) +#define ID(X, ...) X +#define CALL(F, ...) F(__VA_ARGS__) +#define EXPAND(...) __VA_ARGS__ +#define BRACE(...) (__VA_ARGS__) + +#define IF_0(t, f) f +#define IF_1(t, f) t +#define IF_(cond) IF_##cond +#define IF(cond, t, f) IF_(cond)(t, f) + +// add more iterations as needed +#define FOLD_(F, init, x0, x1, x2, x3, x4, x5, x6, x7, ...) \ + F(F(F(F(F(F(F(F(init, x0), x1), x2), x3), x4), x5), x6), x7) +#define FOLD(NIL,...) FOLD_(__VA_ARGS__,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL) + +#define GET1(x, ...) x +#define GET2(x, ...) GET1(__VA_ARGS__) +#define GET3(x, ...) GET2(__VA_ARGS__) + +// add more EQUALS_X_X as needed +#define EQUALS_0_0 ~, 1 +#define EQUALS_1_1 ~, 1 +#define EQUALS_2_2 ~, 1 +#define EQUALS(X, Y) ID(GET2 BRACE(EQUALS_##X##_##Y, 0)) + +/* +#define COMMA(...) , +#define HAS_COMMA(...) HAS_COMMA_1(__VA_ARGS__, COMMA(), ~) +#define HAS_COMMA_1(A, B, ...) HAS_COMMA_2(B, 0, 1, ~) +#define HAS_COMMA_2(A, B, C, ...) C + +#define TRUE(...) 1 +#define FALSE(...) 0 +#define NOT(X) IF(X, 0, 1) +#define OR(A, B) IF(A, 1, B) +#define AND(A, B) IF(A, B, 0) + +#define IS_CALL(X, ...) HAS_COMMA(ID(COMMA X)) + +#define AND3(A, B, C) AND(A, AND(B, C)) + +#define IS_EMPTY(...) AND3( \ + NOT(HAS_COMMA(__VA_ARGS__)), \ + NOT(IS_CALL(__VA_ARGS__)), \ + HAS_COMMA(COMMA __VA_ARGS__ ())) +*/ + +#define T_BYTE (1, GLbyte, GL_BYTE) +#define T_UBYTE (1, GLubyte, GL_UNSIGNED_BYTE) +#define T_SHORT (1, GLshort, GL_SHORT) +#define T_USHORT (1, GLushort, GL_UNSIGNED_SHORT) +#define T_INT (1, GLint, GL_INT) +#define T_UINT (1, GLuint, GL_UNSIGNED_INT) +#define T_FIXED (1, GLfixed, GL_FIXED) +#define T_HALF (1, GLhalf, GL_HALF_FLOAT) +#define T_FLOAT (1, GLfloat, GL_FLOAT) +#define T_DOUBLE (1, GLdouble, GL_DOUBLE) + +#define T_PRESENT(x) ID(GET1 x) +#define T_TYPE(x) ID(GET2 x) +#define T_CONST(x) ID(GET3 x) + +#define VERTEX_DEF_FOLD(struct_name, buf_struct, buf_func, index, type, name, count, ...) ( \ + struct_name, \ + buf_struct T_TYPE(type) name IF(EQUALS(count, 1),,[count]);, \ + buf_func \ + glVertexAttribPointer(index, count, T_CONST(type), \ + GL_FALSE, sizeof(struct struct_name), (GLvoid *) offsetof(struct struct_name, name)); \ + glEnableVertexAttribArray(index);, \ + (1 + index)) + +#define VERTEX_DEF_FOLD_WRAP(buf, attr) \ + IF(T_PRESENT(GET1 attr), CALL(VERTEX_DEF_FOLD, EXPAND buf, EXPAND attr, 1), buf) + +#define VERTEX_DEF_EMIT(name, buf_struct, buf_func, _) \ + struct name { buf_struct }; \ + void name ## _configure_vao() { buf_func }; + +#define VERTEX_DEF(name, ...) ID(VERTEX_DEF_EMIT FOLD(((0, ~, ~), ~, 0), VERTEX_DEF_FOLD_WRAP, \ + (name,,, 0), __VA_ARGS__)) @@ -4,6 +4,7 @@ #include <GL/glew.h> #include <GL/gl.h> #include <GLFW/glfw3.h> +#include "../linmath.h/linmath.h" static void opengl_error(GLenum err, const char *file, int line) { @@ -33,12 +34,22 @@ struct shader { size_t len; }; +int win_width, win_height; + static void framebuffer_size_callback(GLFWwindow *handle, int width, int height) { (void) handle; glViewport(0, 0, width, height); + win_width = width; + win_height = height; } +#define glUniform(loc, x) _Generic((x), \ + GLfloat: glUniform1f, \ + GLint: glUniform1i, \ + GLuint: glUniform1ui \ + )(loc, x) + GLuint shader_program_create(const char *name, struct shader *shaders, size_t num_shaders) { GLuint prog_id = glCreateProgram(); @@ -83,6 +94,13 @@ GLuint shader_program_create(const char *name, struct shader *shaders, size_t nu #define GL_DEBUG opengl_debug(__FILE__, __LINE__); +#include "hacks.h" + +VERTEX_DEF(vertex, + (T_FLOAT, pos, 4), + (T_FLOAT, texCoord, 2) +) + int main() { if (!glfwInit()) { @@ -90,17 +108,23 @@ int main() exit(EXIT_FAILURE); } + //FST(FLOAT) x = 0.0; + //MEOW(int) a = 0; + //int a = MEW(); + //int a = CALL(_1, PAIR(1,2)); + //int b = CALL(_2, FLOAT); + atexit(glfwTerminate); - // glfwWindowHint(GLFW_SAMPLES, 8); + glfwWindowHint(GLFW_SAMPLES, 8); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - int win_w = 1000; - int win_h = 1000; + win_width = 1025; + win_height = 750; - GLFWwindow *window = glfwCreateWindow(win_w, win_h, "Juxtapos", NULL, NULL); + GLFWwindow *window = glfwCreateWindow(win_width, win_height, "Juxtapos", NULL, NULL); if (window == NULL) { fprintf(stderr, "[error] failed to create window\n"); exit(EXIT_FAILURE); @@ -113,11 +137,11 @@ int main() exit(EXIT_FAILURE); } - glViewport(0, 0, win_w, win_h); + glViewport(0, 0, win_width, win_height); glfwSetFramebufferSizeCallback(window, &framebuffer_size_callback); // dimensions of the image - int tex_w = 1000, tex_h = 1000; + int tex_w = 480, tex_h = 480; GLuint wood_texture; glGenTextures(1, &wood_texture); @@ -167,44 +191,135 @@ int main() { "fragment", GL_FRAGMENT_SHADER, fragment_shader_src, sizeof fragment_shader_src }, }, 2); - GLfloat quad[4][2] = { - { -0.5, +0.5 }, - { -0.5, -0.5 }, - { +0.5, +0.5 }, - { +0.5, -0.5 }, - }; + GLint loc_model = glGetUniformLocation(main_shader, "model"); + GLint loc_viewProj = glGetUniformLocation(main_shader, "viewProj"); + + /*struct vertex cube[3][2][2][2]; + for (int i = 0; i < 3; i++) + // for those, i noticed i can replace them with a single loop and use bit manipulation + for (int a = 0; a <= 1; a++) + for (int b = 0; b <= 1; b++) + for (int c = 0; c <= 1; c++) { + struct vertex *v = &cube[i][a][b][c]; + // this simply turned into a loop over k + v->pos[(i+0)%3] = a * 2.0 - 1.0; + v->pos[(i+1)%3] = b * 2.0 - 1.0; + v->pos[(i+2)%3] = c * 2.0 - 1.0; + }*/ + +/*#define DIM 3 + struct vertex vertices[DIM][1 << DIM] = { 0 }; + for (int i = 0; i < DIM; i++) + for (int j = 0; j < 1 << DIM; j++) + for (int k = 0; k < DIM; k++) + vertices[i][j].pos[(i+k)%DIM] = ((j >> k) & 1) * 2.0 - 1.0; +*/ + + /*GLuint indices[DIM][1 << DIM][2]; + for (int i = 0; i < DIM; i++) + for (int j = 0; j < 1 << DIM; j++) + indices[i][j][1] = (indices[i][j][0] = j) ^ (1 << i);*/ + +#define DIM 0 + struct vertex vertices[1 << DIM] = { 0 }; + for (int j = 0; j < 1 << DIM; j++) + for (int k = 0; k < DIM; k++) + vertices[j].pos[k] = ((j >> k) & 1) * 2.0 - 1.0; + +#define BITS_FROM(x, i) ((x) & ((~0U) << (i))) // select all bits above and including bit +#define BITS_TO(x, i) ((x) & ~((~0U) << (i))) // select all bits below bit i + + GLuint indices[DIM][1 << (DIM-1)][2]; + for (unsigned int i = 0; i < DIM; i++) + for (unsigned int j = 0; j < 1 << (DIM-1); j++) + indices[i][j][1] = (indices[i][j][0] = ( + BITS_FROM(j, i) << 1 | BITS_TO(j, i) + )) | (1 << i); + + //for () + + /*GLuint indices[ CUBE_LEN/4 ][8]; + for (int i = 0; i < CUBE_LEN/4; i++) { + for (int j = 0; j < 8; j++) + indices[i][j] = i*4 + (((j+1) % 8) / 2); + }*/ + + /* + GLuint indices[6][6]; + for (int i = 0; i < 6; i++) { + GLuint quad[6] = { 0, 1, 2, 2, 3, 1 }; + for (int j = 0; j < 6; j++) + indices[i][j] = i*4 + quad[j]; + }*/ - GLuint vao, vbo; + /* + struct vertex_quad quad[4] = { + {{ -0.5, +0.5, +0.0 }}, + {{ -0.5, -0.5, +0.0 }}, + {{ +0.5, +0.5, +0.0 }}, + {{ +0.5, -0.5, +0.0 }}, + };*/ + + GLuint vao, vbo, ebo; glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); + glGenBuffers(1, &ebo); glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW); - glBufferData(GL_ARRAY_BUFFER, sizeof quad, quad, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof indices, indices, GL_STATIC_DRAW); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof *quad, 0); - glEnableVertexAttribArray(0); + vertex_configure_vao(); unsigned int skyblue = 0x87ceeb; glClearColor( ((skyblue >> 16) & 0xff) / 255.0, ((skyblue >> 8) & 0xff) / 255.0, ((skyblue >> 0) & 0xff) / 255.0, 1.0); + glPointSize(5.0); glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + + glfwSetTime(0.0); while (!glfwWindowShouldClose(window)) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, GLFW_TRUE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); // preview wood texture glUseProgram(main_shader); + + mat4x4 proj; + mat4x4_perspective(proj, 90.0, (float) win_width / (float) win_height, 0.1, 100.0); + + vec3 up; + vec3_norm(up, (vec3) { 0.0, 1.0, -1.0 }); + + mat4x4 view; + mat4x4_look_at(view, (vec3) { 0.0, 2.0, 2.0 }, (vec3) { 0, 0, 0 }, up); + + mat4x4 view_proj; + mat4x4_mul(view_proj, proj, view); + + mat4x4 id; + mat4x4_identity(id); + mat4x4 model; + mat4x4_rotate_Y(model, id, glfwGetTime() * M_PI * 0.1); + + glUniformMatrix4fv(loc_model, 1, GL_FALSE, &model[0][0]); + glUniformMatrix4fv(loc_viewProj, 1, GL_FALSE, &view_proj[0][0]); + glBindVertexArray(vao); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, wood_texture); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + //glDrawArrays(GL_POINTS, 0, sizeof vertices / sizeof(struct vertex)); + glDrawElements(GL_LINES, sizeof indices / sizeof(GLuint), GL_UNSIGNED_INT, 0); glfwSwapBuffers(window); glfwPollEvents(); |