clean up a lot

This commit is contained in:
sam 2024-05-03 11:18:50 +12:00
parent cb3132e6eb
commit 8cbe81177b
28 changed files with 2929 additions and 166 deletions

2
.gitignore vendored
View file

@ -1,2 +1,2 @@
gearlib
src/*.o
obj/

View file

@ -4,15 +4,18 @@ CC=gcc
CFLAGS=-O3 -Iinclude -g
LDFLAGS=-lglfw -lm
CFILES=$(shell find -L src -type f -name '*.c')
OBJ=$(CFILES:.c=.o)
CFILES=$(shell cd src && find -L * -type f -name '*.c')
OBJ=$(addprefix obj/, $(CFILES:.c=.o))
$(BINARY): $(OBJ) Makefile
$(BINARY): objdir $(OBJ) Makefile
$(CC) $(OBJ) $(LDFLAGS) -o $@
%.o: %.c
obj/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $@
objdir:
mkdir -p obj
run: $(BINARY)
./$(BINARY)

View file

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 123 KiB

BIN
assets/cuddle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

BIN
assets/parrots.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

View file

@ -3,14 +3,11 @@
layout(location = 0) out vec4 color;
struct VertexOutput {
vec4 Tint;
vec2 TexCoord;
vec4 Color;
};
layout(location = 0) in VertexOutput Input;
uniform sampler2D texture0;
void main() {
color = texture(texture0, Input.TexCoord) * Input.Tint;
color = Input.Color;
}

17
assets/quad.vert Normal file
View file

@ -0,0 +1,17 @@
#version 460 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in mat4 a_Transform;
layout(location = 2) in vec4 a_Color;
struct VertexOutput {
vec4 Color;
};
layout(location = 0) out VertexOutput Output;
void main() {
Output.Color = a_Color;
gl_Position = vec4(a_Position, 1.0) * a_Transform;
}

17
assets/texture.frag Normal file
View file

@ -0,0 +1,17 @@
#version 460 core
layout(location = 0) out vec4 color;
struct VertexOutput {
vec4 Tint;
vec2 TexCoord;
};
layout(location = 0) in VertexOutput Input;
layout(location = 2) in flat float TexID;
layout(binding = 0) uniform sampler2D textures[32];
void main() {
color = texture(textures[int(TexID)], Input.TexCoord) * Input.Tint;
}

View file

@ -3,6 +3,7 @@
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec4 a_Tint;
layout(location = 2) in vec2 a_TexCoord;
layout(location = 3) in float a_TexID;
struct VertexOutput {
vec4 Tint;
@ -10,10 +11,12 @@ struct VertexOutput {
};
layout(location = 0) out VertexOutput Output;
layout(location = 2) out flat float TexID;
void main() {
Output.Tint = a_Tint;
Output.TexCoord = a_TexCoord;
TexID = a_TexID;
gl_Position = vec4(a_Position, 1.0);
}

39
include/batch.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef __BATCH_H__
#define __BATCH_H__
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <gearlib.h>
typedef struct BatchStats {
uint32_t draw_calls;
uint32_t total_verts;
} BatchStats;
typedef struct RenderBatch {
uint32_t vbo;
uint32_t vao;
uint32_t shader;
void* vertices;
void* vertex_ptr;
size_t vertex_size;
uint32_t vertex_count;
uint32_t max_vertices;
VertexLayout layout;
BatchStats stats;
void* data;
void (*flush_callback)(struct RenderBatch*);
} RenderBatch;
RenderBatch* create_batch(size_t vert_size, uint32_t max_verts);
void flush();
void flush_batch(RenderBatch* batch);
void batch_add_attrib(RenderBatch* batch, VertexAttrib attr);
void batch_bind_attribs(RenderBatch* batch);
bool batch_needs_flush(RenderBatch* batch, uint32_t vertex_add);
#endif

View file

@ -1,7 +1,7 @@
#ifndef __EVENTS_H__
#define __EVENTS_H__
#include <types.h>
#include <gearlib.h>
void framebuffer_size_callback(Window window, int width, int height);
void process_input(Window window);

17
include/gearlib.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef __GEARLIB_H__
#define __GEARLIB_H__
#define MAX_VERTICES 1000
#include <raymath.h>
#include <init.h>
#include <shaders.h>
#include <events.h>
#include <debugging.h>
#include <vertex.h>
#include <renderer.h>
#include <batch.h>
#include <quad.h>
#include <textures.h>
#endif

View file

@ -1,7 +1,9 @@
#ifndef __INIT_H__
#define __INIT_H__
#include <types.h>
#include <opengl.h>
typedef GLFWwindow* Window;
void init_gl(int major, int minor);
Window create_window(int width, int height, const char* title);

14
include/quad.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef __QUAD_H__
#define __QUAD_H__
#include <gearlib.h>
typedef struct {
vec3 Position;
mat4 Transform;
vec4 Color;
} QuadVertex;
extern vec3 quad_vertex_positions[6];
#endif

2527
include/raymath.h Normal file

File diff suppressed because it is too large Load diff

8
include/renderer.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef __RENDERER_H__
#define __RENDERER_H__
#include <stdint.h>
void renderer_draw(uint32_t vao, int count);
#endif

View file

@ -1,8 +1,27 @@
#ifndef __TEXTURES_H__
#define __TEXTURES_H__
#include <gearlib.h>
#include <stdint.h>
void setup_textures();
uint32_t load_texture(const char* path);
void draw_texture(uint32_t id, vec3 pos, vec4 color);
void batch_draw_texture(RenderBatch* batch, uint32_t id, vec3 pos, vec4 color);
RenderBatch* create_texture_quad_batch();
extern RenderBatch* texture_quad_batch;
extern int max_textures;
typedef struct {
vec3 Position;
vec4 Tint;
vec2 TexCoord;
float TexID;
} TextureQuadVertex;
typedef struct {
float texture_index;
} TextureQuadBatchData;
#endif

View file

@ -1,20 +0,0 @@
#ifndef __TYPES_H__
#define __TYPES_H__
#include <opengl.h>
typedef GLFWwindow* Window;
typedef struct {
float x, y;
} float2;
typedef struct {
float x, y, z;
} float3;
typedef struct {
float x, y, z, w;
} float4;
#endif

18
include/vertex.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef __VERTEX_H__
#define __VERTEX_H__
#include <stddef.h>
typedef struct VertexAttrib {
int type;
size_t size;
int count;
} VertexAttrib;
typedef struct VertexLayout {
VertexAttrib* data;
size_t size;
size_t capacity;
} VertexLayout;
#endif

74
src/batch.c Normal file
View file

@ -0,0 +1,74 @@
#include <gearlib.h>
#include <stdlib.h>
#include <slibs.h>
sl_vec(RenderBatch*) batches = { 0 };
RenderBatch* create_batch(size_t vert_size, uint32_t max_verts) {
RenderBatch* batch = calloc(sizeof(RenderBatch), 1);
sl_vec_push(batches, batch);
glCreateBuffers(1, &batch->vbo);
glCreateVertexArrays(1, &batch->vao);
batch->vertex_size = vert_size;
batch->max_vertices = max_verts;
batch->vertices = calloc(vert_size, max_verts);
batch->vertex_ptr = batch->vertices;
glNamedBufferStorage(batch->vbo, vert_size * max_verts, NULL, GL_DYNAMIC_STORAGE_BIT);
return batch;
}
void flush() {
for(int i = 0; i < batches.size; i++) {
RenderBatch* batch = batches.data[i];
batch->stats.total_verts = 0;
batch->stats.draw_calls = 0;
flush_batch(batch);
}
}
void flush_batch(RenderBatch* batch) {
batch->stats.total_verts += batch->vertex_count;
glUseProgram(batch->shader);
if(batch->flush_callback != NULL)
batch->flush_callback(batch);
glNamedBufferSubData(batch->vbo, 0, batch->vertex_size * batch->vertex_count, batch->vertices);
renderer_draw(batch->vao, batch->vertex_count);
batch->vertex_count = 0;
batch->vertex_ptr = batch->vertices;
glUseProgram(0);
batch->stats.draw_calls++;
}
void batch_add_attrib(RenderBatch* batch, VertexAttrib attr) {
sl_vec_push(batch->layout, attr);
}
void batch_bind_attribs(RenderBatch* batch) {
size_t stride = 0;
for(int i = 0; i < batch->layout.size; i++) {
VertexAttrib attr = batch->layout.data[i];
glEnableVertexArrayAttrib(batch->vao, i);
glVertexArrayAttribFormat(batch->vao, i, attr.count, attr.type, GL_FALSE, stride);
glVertexArrayAttribBinding(batch->vao, i, 0);
stride += attr.size * attr.count;
}
glVertexArrayVertexBuffer(batch->vao, 0, batch->vbo, 0, stride);
}
bool batch_needs_flush(RenderBatch* batch, uint32_t vertex_add) {
//return true;
return batch->vertex_size * (batch->vertex_count + vertex_add) >= batch->vertex_size * batch->max_vertices;
}

View file

@ -1,4 +1,4 @@
#include <events.h>
#include <gearlib.h>
void framebuffer_size_callback(Window window, int width, int height) {
glViewport(0, 0, width, height);

View file

@ -1,3 +1,6 @@
#define SL_IMPLEMENTATION
#include <slibs.h>
#define STBI_FAILURE_USERMSG
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

View file

@ -1,8 +1,6 @@
#include <init.h>
#include <gearlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <events.h>
#include <opengl.h>
void init_gl(int major, int minor) {
@ -15,7 +13,7 @@ void init_gl(int major, int minor) {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
}
Window create_window(int width, int height, const char* title) {
@ -39,5 +37,8 @@ Window create_window(int width, int height, const char* title) {
glViewport(0, 0, width, height);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
return window;
}

View file

@ -1,130 +1,20 @@
#include <init.h>
#include <debugging.h>
#include <shaders.h>
#include <textures.h>
#include <events.h>
#include <types.h>
#include <gearlib.h>
#include <stdlib.h>
#define MAX_VERTICES 1000
#define ARR_SIZE(arr) sizeof(arr)/sizeof(arr[0])
typedef struct {
int type;
size_t size;
int count;
} VertexAttrib;
typedef struct {
float3 Position;
float4 Color;
float2 TexCoord;
} QuadVertex;
VertexAttrib quad_attribs[] = {
{ .type = GL_FLOAT, .size = sizeof(float), .count = 3 }, // position
{ .type = GL_FLOAT, .size = sizeof(float), .count = 4 }, // color
{ .type = GL_FLOAT, .size = sizeof(float), .count = 2 }, // texcoord
};
uint32_t index_count = 0;
uint32_t vertex_count = 0;
uint32_t texture_shader, quad_vbo, quad_vao;
QuadVertex* quad_vertices;
QuadVertex* current_quad_vertex;
void load_default_shaders() {
texture_shader = load_shader_program(
compile_shader("texture.vert", GL_VERTEX_SHADER),
compile_shader("texture.frag", GL_FRAGMENT_SHADER), 0);
}
float3 quad_vertex_positions[4] = {
{ -0.5f, 0.5f, 0.0f },
{ -0.5f, -0.5f, 0.0f },
{ 0.5f, -0.5f, 0.0f },
{ 0.5f, 0.5f, 0.0f }
};
void draw_indexed(uint32_t vao, int count) {
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
void flush() {
glNamedBufferSubData(quad_vbo, 0, sizeof(QuadVertex) * vertex_count, quad_vertices);
draw_indexed(quad_vao, index_count);
vertex_count = 0;
index_count = 0;
current_quad_vertex = quad_vertices;
}
void draw_texture(uint32_t texture, float4 color) {
if(vertex_count > MAX_VERTICES - 4)
flush();
float2 texcoords[] = {
{ 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 0.0f, 1.0f },
{ 1.0f, 1.0f }
};
for(int i = 0; i < 4; i++) {
current_quad_vertex->Position = quad_vertex_positions[i];
current_quad_vertex->Color = color;
current_quad_vertex->TexCoord = texcoords[i];
current_quad_vertex++;
vertex_count++;
}
index_count += 6;
}
#include <raymath.h>
int main() {
init_gl(4, 6);
Window window = create_window(800, 600, "gearlib");
glfwSwapInterval(0);
enable_debugging();
load_default_shaders();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
quad_vertices = malloc(sizeof(QuadVertex) * MAX_VERTICES);
current_quad_vertex = quad_vertices;
glCreateBuffers(1, &quad_vbo);
glNamedBufferStorage(quad_vbo, sizeof(QuadVertex) * MAX_VERTICES, NULL, GL_DYNAMIC_STORAGE_BIT);
uint32_t quad_indices[] = {
0, 1, 3,
1, 2, 3
};
uint32_t quad_ibo;
glCreateBuffers(1, &quad_ibo);
glNamedBufferStorage(quad_ibo, sizeof(quad_indices), quad_indices, GL_DYNAMIC_STORAGE_BIT);
glCreateVertexArrays(1, &quad_vao);
size_t stride = 0;
for(int i = 0; i < ARR_SIZE(quad_attribs); i++) {
VertexAttrib attr = quad_attribs[i];
glEnableVertexArrayAttrib(quad_vao, i);
glVertexArrayAttribFormat(quad_vao, i, attr.count, attr.type, GL_FALSE, stride);
glVertexArrayAttribBinding(quad_vao, i, 0);
stride += attr.size * attr.count;
}
glVertexArrayVertexBuffer(quad_vao, 0, quad_vbo, 0, stride);
glVertexArrayElementBuffer(quad_vao, quad_ibo);
setup_textures();
uint32_t cat = load_texture("cat.png");
uint32_t cat = load_texture("assets/cat.png");
uint32_t cuddle = load_texture("assets/cuddle.png");
uint32_t parrots = load_texture("assets/parrots.png");
double time = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
process_input(window);
@ -132,14 +22,18 @@ int main() {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindTextureUnit(0, cat);
glUseProgram(texture_shader);
draw_texture(parrots, (vec3){ -0.4f, 0.4f, 0.0f }, (vec4){ 1.0f, 1.0f, 1.0f, 1.0f });
draw_texture(cat, (vec3){ 0.0f, 0.0f, 0.0f }, (vec4){ 1.0f, 1.0f, 1.0f, 1.0f });
draw_texture(cuddle, (vec3){ 0.0f, -0.4f, 0.0f }, (vec4){ 1.0f, 1.0f, 1.0f, 1.0f });
for(int i = 0; i < 10000; i++) {
draw_texture(cat, (float4){ 1.0f, 1.0f, 1.0f, 1.0f });
}
flush();
flush();
double end_time = glfwGetTime();
double frame_time = end_time - time;
double fps = 1 / frame_time;
time = end_time;
//printf("%lf, %lf" /*", %d, %d"*/ "\n", frame_time, fps/*, stats.draw_calls, stats.total_verts*/);
glfwSwapBuffers(window);
glfwPollEvents();

43
src/quad.c Normal file
View file

@ -0,0 +1,43 @@
#include <gearlib.h>
vec3 quad_vertex_positions[6] = {
{ -0.5f, 0.5f, 0.0f },
{ -0.5f, -0.5f, 0.0f },
{ 0.5f, -0.5f, 0.0f },
{ -0.5f, 0.5f, 0.0f },
{ 0.5f, -0.5f, 0.0f },
{ 0.5f, 0.5f, 0.0f },
};
void draw_rectangle(RenderBatch* batch, mat4 transform, vec4 color) {
if(batch_needs_flush(batch, 6))
flush_batch(batch);
for(int i = 0; i < 6; i++) {
QuadVertex* vertex = batch->vertex_ptr;
vertex->Position = quad_vertex_positions[i];
vertex->Color = color;
batch->vertex_ptr += batch->vertex_size;
batch->vertex_count++;
}
}
void setup_quad() {
RenderBatch* quad_batch = create_batch(sizeof(QuadVertex), MAX_VERTICES);
quad_batch->shader = load_shader_program(
compile_shader("assets/quad.vert", GL_VERTEX_SHADER),
compile_shader("assets/quad.frag", GL_FRAGMENT_SHADER), 0);;
batch_add_attrib(quad_batch, (VertexAttrib){
.type = GL_FLOAT, .size = sizeof(float), .count = 3
}); // pos
batch_add_attrib(quad_batch, (VertexAttrib){
.type = GL_FLOAT, .size = sizeof(float), .count = 4
}); // color
batch_bind_attribs(quad_batch);
}

8
src/renderer.c Normal file
View file

@ -0,0 +1,8 @@
#include <gearlib.h>
#include <opengl.h>
void renderer_draw(uint32_t vao, int count) {
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, count);
glBindVertexArray(0);
}

View file

@ -1,2 +0,0 @@
#define SL_IMPLEMENTATION
#include <slibs.h>

View file

@ -3,6 +3,16 @@
#include <opengl.h>
#include <stdio.h>
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) {
stbi_set_flip_vertically_on_load(1);
@ -15,7 +25,7 @@ uint32_t load_texture(const char* path) {
glTextureParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, channels;
unsigned char* pixels = stbi_load(path, &width, &height, &channels, 0);
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);
@ -27,3 +37,74 @@ uint32_t load_texture(const char* path) {
return id;
}
void draw_texture(uint32_t id, vec3 pos, vec4 color) {
batch_draw_texture(texture_quad_batch, id, pos, color);
}
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 batch_draw_texture(RenderBatch* batch, uint32_t texture, vec3 pos, 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 = vec3Add(quad_vertex_positions[i], pos);
vertex->Tint = color;
vertex->TexCoord = texture_quad_texcoords[i];
vertex->TexID = tex_id;
batch->vertex_ptr += batch->vertex_size;
batch->vertex_count++;
}
}
void texture_quad_batch_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_quad_batch_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;
}