diff --git a/.gitignore b/.gitignore index 6b9ebd9..6d45ee2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -libgearlib.a -obj/ -test/*.exe +*.a +obj/ +examples/*.exe diff --git a/Makefile b/Makefile index 48fcc5e..2929a13 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,25 @@ -LIBRARY=libgearlib.a - -CC:=gcc -AR=ar -CFLAGS=-O3 -Iinclude -g -LDFLAGS=-lglfw -lm - -CFILES=$(shell cd src && mingw32-find -L * -type f -name '*.c') -OBJDIR=obj -OBJ=$(addprefix $(OBJDIR)/, $(CFILES:.c=.o)) - -$(LIBRARY): $(OBJ) Makefile - $(AR) rcs $(LIBRARY) $(OBJ) - -obj/%.o: src/%.c - mkdir -p $(OBJDIR) - $(CC) $(CFLAGS) -c $< -o $@ - -run: $(LIBRARY) - make -C examples test - cd examples && ./test - -clean: - rm -rf $(OBJ) $(LIBRARY) - make -C test clean +LIBRARY=libgearlib.a + +CC:=gcc +AR=ar +CFLAGS=-O3 -Iinclude -g +LDFLAGS=-lglfw -lm + +CFILES=$(shell cd src && find -L * -type f -name '*.c') +OBJDIR=obj +OBJ=$(addprefix $(OBJDIR)/, $(CFILES:.c=.o)) + +$(LIBRARY): $(OBJ) Makefile + $(AR) rcs $(LIBRARY) $(OBJ) + +obj/%.o: src/%.c + mkdir -p $(OBJDIR) + $(CC) $(CFLAGS) -c $< -o $@ + +run: $(LIBRARY) + make -C examples test + cd examples && ./test + +clean: + rm -rf $(OBJ) $(LIBRARY) + make -C examples clean diff --git a/examples/Makefile b/examples/Makefile index 4d91e1e..876b0b9 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,16 +1,16 @@ -CC=gcc - -CFLAGS=-O3 -I../include -LDFLAGS=C:\msys64\ucrt64\lib\libglfw3.a -L ../ -lgdi32 -lgearlib -lm - -CFILES=$(shell mingw32-find -L * -type f -name '*.c') -BINARIES=$(CFILES:.c=) - -all: $(BINARIES) - -%: %.c - $(CC) $< -o $@ $(CFLAGS) $(LDFLAGS) - -clean: - rm -rf $(BINARIES) - +CC=gcc + +CFLAGS = -O3 -I../include +LDFLAGS = -L ../ -lglfw -lgearlib -lm + +CFILES=$(shell find -L * -type f -name '*.c') +BINARIES=$(CFILES:.c=) + +all: $(BINARIES) + +%: %.c + $(CC) $< -o $@ $(CFLAGS) $(LDFLAGS) + +clean: + rm -rf $(BINARIES) + diff --git a/examples/test b/examples/test deleted file mode 100755 index df1c972..0000000 Binary files a/examples/test and /dev/null differ diff --git a/examples/test.c b/examples/test.c index 272eeba..d0c779a 100644 --- a/examples/test.c +++ b/examples/test.c @@ -1,35 +1,44 @@ -#include - -int main() { - Window window = create_window(800, 600, "test"); - glfwSwapInterval(0); // fps unlock - enable_debugging(); - setup_textures(); - - Camera* camera = create_camera(vec2(0.0f, 0.0f)); - UniformBuffer* camera_buffer = create_uniform_buffer(sizeof(CameraMatrices)); - - Texture cat = load_texture("assets/cat.png"); - - while (!glfwWindowShouldClose(window)) { - process_input(window); - update_camera(camera, window); - set_uniform_data(camera_buffer, camera->m); - - glClearColor(vec4_spread(BLACK)); - glClear(GL_COLOR_BUFFER_BIT); - - for(int i = 0; i < 32; i++) { - draw_texture(cat, vec2(rand() % 600, rand() % 600), vec2(500.0f, 500.0f), WHITE); - } - - flush(); - - glfwSwapBuffers(window); - glfwPollEvents(); - } - - glfwDestroyWindow(window); - glfwTerminate(); - return 0; -} +#include + +int main() { + Window window = create_window(800, 600, "test"); + glfwSwapInterval(0); // fps unlock + enable_debugging(); + setup_textures(); + + Camera* camera = create_camera(vec2(0.0f, 0.0f)); + UniformBuffer* camera_buffer = create_uniform_buffer(sizeof(CameraMatrices)); + + Texture cat = load_texture("assets/cat.png"); + + double time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + process_input(window); + update_camera(camera, window); + set_uniform_data(camera_buffer, camera->m); + + glClearColor(vec4_spread(BLACK)); + glClear(GL_COLOR_BUFFER_BIT); + + for(int i = 0; i < 32; i++) { + draw_texture(cat, vec2(rand() % 600, rand() % 600), vec2(500.0f, 500.0f), WHITE); + } + + flush(); + + double end_time = glfwGetTime(); + double frame_time = end_time - time; + time = end_time; + + double fps = 1.0 / frame_time; + printf("frame_time: %lf fps: %lf\n", frame_time, fps); + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/examples/test.exe b/examples/test.exe index 35a279f..c85d807 100644 Binary files a/examples/test.exe and b/examples/test.exe differ diff --git a/examples/textures b/examples/textures deleted file mode 100755 index 12f5133..0000000 Binary files a/examples/textures and /dev/null differ diff --git a/examples/textures.c b/examples/textures.c index e8b75a0..0c7809b 100644 --- a/examples/textures.c +++ b/examples/textures.c @@ -1,32 +1,41 @@ -#include - -int main() { - Window window = create_window(800, 600, "textures"); - glfwSwapInterval(0); // fps unlock - setup_textures(); - - Camera* camera = create_camera(vec2(0.0f, 0.0f)); - UniformBuffer* camera_buffer = create_uniform_buffer(sizeof(CameraMatrices)); - - Texture cat = load_texture("assets/cat.png"); - - while (!glfwWindowShouldClose(window)) { - process_input(window); - update_camera(camera, window); - set_uniform_data(camera_buffer, camera->m); - - glClearColor(vec4_spread(BLACK)); - glClear(GL_COLOR_BUFFER_BIT); - - draw_texture(cat, vec2(250.0f, 250.0f), vec2(500.0f, 500.0f), WHITE); - - flush(); - - glfwSwapBuffers(window); - glfwPollEvents(); - } - - glfwDestroyWindow(window); - glfwTerminate(); - return 0; -} +#include + +int main() { + Window window = create_window(800, 600, "textures"); + glfwSwapInterval(0); // fps unlock + setup_textures(); + + Camera* camera = create_camera(vec2(0.0f, 0.0f)); + UniformBuffer* camera_buffer = create_uniform_buffer(sizeof(CameraMatrices)); + + Texture cat = load_texture("assets/cat.png"); + + double time = glfwGetTime(); + + while (!glfwWindowShouldClose(window)) { + process_input(window); + update_camera(camera, window); + set_uniform_data(camera_buffer, camera->m); + + glClearColor(vec4_spread(BLUE)); + glClear(GL_COLOR_BUFFER_BIT); + + draw_texture(cat, vec2(250.0f, 250.0f), vec2(500.0f, 500.0f), WHITE); + + flush(); + + double end_time = glfwGetTime(); + double frame_time = end_time - time; + time = end_time; + + double fps = 1.0 / frame_time; + printf("frame_time: %lf fps: %lf\n", frame_time, fps); + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glfwDestroyWindow(window); + glfwTerminate(); + return 0; +} diff --git a/src/.textures.c.swp b/src/.textures.c.swp new file mode 100644 index 0000000..a34c85d Binary files /dev/null and b/src/.textures.c.swp differ diff --git a/src/textures.c b/src/textures.c index 215ddce..1192f21 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1,119 +1,129 @@ -#include -#include -#include -#include -#include - -RenderBatch* texture_quad_batch = NULL; -int max_textures; - -void setup_textures() { - texture_quad_batch = create_texture_quad_batch(); - - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_textures); - if(max_textures > 32) max_textures = 32; -} - -uint32_t load_texture(const char* path) { - uint32_t id; - glCreateTextures(GL_TEXTURE_2D, 1, &id); - - glTextureParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTextureParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTextureParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - int width, height, channels; - unsigned char* pixels = stbi_load(path, &width, &height, &channels, 4); - if(pixels) { - glTextureStorage2D(id, 1, GL_RGBA8, width, height); - glTextureSubImage2D(id, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - printf("[Texture %d, %s] Loaded successfully (%dx%d, %d channels)\n", id, path, width, height, channels); - } else { - printf("[Texture %d, %s] Failed to load image data: %s\n", id, path, stbi_failure_reason()); - exit(-1); - } - - return id; -} - -vec2 texture_quad_texcoords[] = { - { 0.0f, 1.0f }, - { 0.0f, 0.0f }, - { 1.0f, 0.0f }, - - { 0.0f, 1.0f }, - { 1.0f, 0.0f }, - { 1.0f, 1.0f } -}; - -void draw_texture(Texture id, vec2 pos, vec2 size, vec4 tint) { - mat4 transform = mat4Multiply( - mat4Scale(size.x, size.y, 1.0f), - mat4Translate(pos.x, pos.y, 0.0f)); - - draw_texture_trans(id, transform, tint); -} - -void draw_texture_trans(Texture id, mat4 transform, vec4 tint) { - assert(texture_quad_batch != NULL && "texture_quad_batch is null, was setup_textures() called?"); - batch_draw_texture(texture_quad_batch, id, transform, tint); -} - -void batch_draw_texture(RenderBatch* batch, Texture texture, mat4 transform, vec4 color) { - TextureQuadBatchData* batch_data = batch->data; - uint32_t vertex_add = 6; - - if(batch_needs_flush(batch, vertex_add) || batch_data->texture_index >= max_textures) - flush_batch(batch); - - uint32_t tex_id = batch_data->texture_index++; - glBindTextureUnit(tex_id, texture); - - for(int i = 0; i < vertex_add; i++) { - TextureQuadVertex* vertex = batch->vertex_ptr; - - vertex->Position = vec3Transform(quad_vertex_positions[i], transform); - vertex->Tint = color; - vertex->TexCoord = texture_quad_texcoords[i]; - vertex->TexID = tex_id; - - batch->vertex_ptr += batch->vertex_size; - batch->vertex_count++; - } -} - -void texture_flush_callback(RenderBatch* batch) { - TextureQuadBatchData* data = batch->data; - data->texture_index = 0; -} - -RenderBatch* create_texture_quad_batch() { - RenderBatch* texture_quad_batch = create_batch(sizeof(TextureQuadVertex), MAX_VERTICES); - texture_quad_batch->shader = load_shader_program( - compile_shader("assets/texture.vert", GL_VERTEX_SHADER), - compile_shader("assets/texture.frag", GL_FRAGMENT_SHADER), 0); - - texture_quad_batch->data = calloc(sizeof(TextureQuadBatchData), 1); - texture_quad_batch->flush_callback = &texture_flush_callback; - - batch_add_attrib(texture_quad_batch, (VertexAttrib){ - .type = GL_FLOAT, .size = sizeof(float), .count = 3 - }); // pos - - batch_add_attrib(texture_quad_batch, (VertexAttrib){ - .type = GL_FLOAT, .size = sizeof(float), .count = 4 - }); // color - - batch_add_attrib(texture_quad_batch, (VertexAttrib){ - .type = GL_FLOAT, .size = sizeof(float), .count = 2 - }); // texcoord - - batch_add_attrib(texture_quad_batch, (VertexAttrib){ - .type = GL_FLOAT, .size = sizeof(float), .count = 1 - }); // texid - - batch_bind_attribs(texture_quad_batch); - - return texture_quad_batch; -} +#include +#include +#include +#include +#include + +RenderBatch* texture_quad_batch = NULL; +int max_textures; + +void setup_textures() { + texture_quad_batch = create_texture_quad_batch(); + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_textures); + if(max_textures > 32) max_textures = 32; +} + +uint32_t load_texture(const char* path) { + uint32_t id; + glCreateTextures(GL_TEXTURE_2D, 1, &id); + + uint8_t default_texture[] = { + 0, 0, 0, 255, 255, 0, 255, 255, + 255, 0, 255, 255, 0, 0, 0, 255 }; + + int width = 2, height = 2, channels; + uint8_t* pixels = stbi_load(path, &width, &height, &channels, 4); + if(pixels) { + glTextureParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTextureParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTextureParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTextureStorage2D(id, 1, GL_RGBA8, width, height); + glTextureSubImage2D(id, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + printf("[Texture %d, %s] Loaded successfully (%dx%d, %d channels)\n", id, path, width, height, channels); + } else { + glTextureParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTextureParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTextureParameteri(id, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glTextureStorage2D(id, 1, GL_RGBA8, width, height); + glTextureSubImage2D(id, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, default_texture); + printf("[Texture %d, %s] Failed to load image data: %s\n", id, path, stbi_failure_reason()); + } + + return id; +} + +vec2 texture_quad_texcoords[] = { + { 0.0f, 1.0f }, + { 0.0f, 0.0f }, + { 1.0f, 0.0f }, + + { 0.0f, 1.0f }, + { 1.0f, 0.0f }, + { 1.0f, 1.0f } +}; + +void draw_texture(Texture id, vec2 pos, vec2 size, vec4 tint) { + mat4 transform = mat4Multiply( + mat4Scale(size.x, size.y, 1.0f), + mat4Translate(pos.x, pos.y, 0.0f)); + + draw_texture_trans(id, transform, tint); +} + +void draw_texture_trans(Texture id, mat4 transform, vec4 tint) { + assert(texture_quad_batch != NULL && "texture_quad_batch is null, was setup_textures() called?"); + batch_draw_texture(texture_quad_batch, id, transform, tint); +} + +void batch_draw_texture(RenderBatch* batch, Texture texture, mat4 transform, vec4 color) { + TextureQuadBatchData* batch_data = batch->data; + uint32_t vertex_add = 6; + + if(batch_needs_flush(batch, vertex_add) || batch_data->texture_index >= max_textures) + flush_batch(batch); + + uint32_t tex_id = batch_data->texture_index++; + glBindTextureUnit(tex_id, texture); + + for(int i = 0; i < vertex_add; i++) { + TextureQuadVertex* vertex = batch->vertex_ptr; + + vertex->Position = vec3Transform(quad_vertex_positions[i], transform); + vertex->Tint = color; + vertex->TexCoord = texture_quad_texcoords[i]; + vertex->TexID = tex_id; + + batch->vertex_ptr += batch->vertex_size; + batch->vertex_count++; + } +} + +void texture_flush_callback(RenderBatch* batch) { + TextureQuadBatchData* data = batch->data; + data->texture_index = 0; +} + +RenderBatch* create_texture_quad_batch() { + RenderBatch* texture_quad_batch = create_batch(sizeof(TextureQuadVertex), MAX_VERTICES); + texture_quad_batch->shader = load_shader_program( + compile_shader("assets/texture.vert", GL_VERTEX_SHADER), + compile_shader("assets/texture.frag", GL_FRAGMENT_SHADER), 0); + + texture_quad_batch->data = calloc(sizeof(TextureQuadBatchData), 1); + texture_quad_batch->flush_callback = &texture_flush_callback; + + batch_add_attrib(texture_quad_batch, (VertexAttrib){ + .type = GL_FLOAT, .size = sizeof(float), .count = 3 + }); // pos + + batch_add_attrib(texture_quad_batch, (VertexAttrib){ + .type = GL_FLOAT, .size = sizeof(float), .count = 4 + }); // color + + batch_add_attrib(texture_quad_batch, (VertexAttrib){ + .type = GL_FLOAT, .size = sizeof(float), .count = 2 + }); // texcoord + + batch_add_attrib(texture_quad_batch, (VertexAttrib){ + .type = GL_FLOAT, .size = sizeof(float), .count = 1 + }); // texid + + batch_bind_attribs(texture_quad_batch); + + return texture_quad_batch; +}