summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDrNuget <drnuget@outlook.com>2026-01-07 04:58:54 +0200
committerDrNuget <drnuget@outlook.com>2026-01-07 04:58:54 +0200
commit7f3aa1cff755d21d972457b05c140cf465b9fa19 (patch)
tree748b74a65d71ead9d0d7ade533074c5a643076d7 /src
parent67592a66dd9bcc4d79d23624a9abfd8f2c6e92ff (diff)
downloadmnm-7f3aa1cff755d21d972457b05c140cf465b9fa19.tar.gz
some basic 3D rendering and the base for chunk generation etc.
Diffstat (limited to 'src')
-rw-r--r--src/engine/M_block.c33
-rw-r--r--src/engine/M_block.h26
-rw-r--r--src/engine/M_camera.c30
-rw-r--r--src/engine/M_camera.h19
-rw-r--r--src/engine/M_chunk.c24
-rw-r--r--src/engine/M_chunk.h17
-rw-r--r--src/engine/M_cube.c39
-rw-r--r--src/engine/M_cube.h4
-rw-r--r--src/engine/M_game.c66
-rw-r--r--src/engine/M_game.h33
-rw-r--r--src/engine/M_main.c48
-rw-r--r--src/engine/M_object.c108
-rw-r--r--src/engine/M_object.h64
-rw-r--r--src/engine/M_player.c32
-rw-r--r--src/engine/M_player.h16
-rw-r--r--src/engine/M_render.c17
-rw-r--r--src/engine/M_render.h16
-rw-r--r--src/engine/M_shader.c57
-rw-r--r--src/engine/M_shader.h21
-rw-r--r--src/engine/M_types.h10
-rw-r--r--src/shaders/basic.frag6
-rw-r--r--src/shaders/basic.vert6
-rw-r--r--src/shaders/test.frag17
-rw-r--r--src/shaders/test.vert19
24 files changed, 728 insertions, 0 deletions
diff --git a/src/engine/M_block.c b/src/engine/M_block.c
new file mode 100644
index 0000000..0f3fb27
--- /dev/null
+++ b/src/engine/M_block.c
@@ -0,0 +1,33 @@
+#include "M_block.h"
+
+void M_createBlock(M_Block *block, unsigned short type)
+{
+ block->type = type;
+}
+
+unsigned short M_createBlockType(M_Object obj, M_BlockAtlas *atl)
+{
+ M_BlockType block_type;
+ block_type.obj = obj;
+
+ if (atl->block_amount >= atl->size) {
+ atl->size += 10;
+ atl->blocks = realloc(atl->blocks, atl->size*sizeof(M_BlockType));
+ }
+ atl->blocks[atl->block_amount++] = block_type;
+ return atl->block_amount;
+}
+
+M_BlockAtlas M_createBlockAtlas()
+{
+ return (M_BlockAtlas){
+ .blocks = malloc(10*sizeof(M_BlockType)),
+ .block_amount = 0,
+ .size = 10
+ };
+}
+
+void M_killBlockAtlas(M_BlockAtlas *atl)
+{
+ free(atl->blocks);
+}
diff --git a/src/engine/M_block.h b/src/engine/M_block.h
new file mode 100644
index 0000000..852830c
--- /dev/null
+++ b/src/engine/M_block.h
@@ -0,0 +1,26 @@
+#pragma once
+
+//#include "M_types.ḥ"
+#include "M_object.h"
+
+typedef struct {
+ unsigned short type;
+} M_Block;
+
+typedef struct {
+ M_Object obj;
+} M_BlockType;
+
+typedef struct {
+ M_BlockType *blocks;
+ unsigned short block_amount;
+ unsigned short size;
+} M_BlockAtlas;
+
+void M_createBlock(M_Block *block, unsigned short type);
+
+unsigned short M_createBlockType(M_Object obj, M_BlockAtlas *atl);
+
+M_BlockAtlas M_createBlockAtlas();
+
+void M_killBlockAtlas(M_BlockAtlas *atl);
diff --git a/src/engine/M_camera.c b/src/engine/M_camera.c
new file mode 100644
index 0000000..58414a7
--- /dev/null
+++ b/src/engine/M_camera.c
@@ -0,0 +1,30 @@
+#include "M_camera.h"
+
+void M_initCamera(M_Camera *camera, vec3 up)
+{
+ glm_vec3_zero(camera->pos);
+ glm_vec3_copy(
+ up,
+ camera->up
+ );
+ glm_vec3_copy(
+ (vec3){0.0f, 0.0f, -1.0f},
+ camera->direction
+ );
+}
+
+inline void M_cameraViewMatrix(M_Camera* camera)
+{
+ vec3 target;
+ glm_vec3_add(
+ camera->pos,
+ camera->direction,
+ target
+ );
+ glm_lookat(
+ camera->pos,
+ target,
+ camera->up,
+ camera->view_matrix
+ );
+}
diff --git a/src/engine/M_camera.h b/src/engine/M_camera.h
new file mode 100644
index 0000000..4663a94
--- /dev/null
+++ b/src/engine/M_camera.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <cglm/cglm.h>
+#include <cglm/mat4.h>
+#include <cglm/vec3.h>
+
+typedef struct {
+ vec3 pos;
+ vec3 direction;
+ vec3 up;
+
+ mat4 view_matrix;
+} M_Camera;
+
+
+void M_initCamera(M_Camera *camera, vec3 up);
+
+//Generates the M_Camera's view matrix required for rendering
+void M_cameraViewMatrix(M_Camera *camera);
diff --git a/src/engine/M_chunk.c b/src/engine/M_chunk.c
new file mode 100644
index 0000000..5c120f5
--- /dev/null
+++ b/src/engine/M_chunk.c
@@ -0,0 +1,24 @@
+#include "M_chunk.h"
+
+void M_generateChunk(M_Chunk *chunk)
+{
+ for (int x=0;x<M_CHUNK_SIZE;x++)
+ for (int y=0;y<M_CHUNK_SIZE;y++)
+ for (int z=0;z<M_CHUNK_SIZE;z++) {
+ M_Block block;
+ M_createBlock(&block, 0);
+ chunk->blocks[x][y][z] = block;
+ }
+}
+
+void M_renderChunk(M_Game *game, M_Chunk *chunk)
+{
+ for (int x=0;x<M_CHUNK_SIZE;x++)
+ for (int y=0;y<M_CHUNK_SIZE;y++)
+ for (int z=0;z<M_CHUNK_SIZE;z++) {
+ M_Block block = chunk->blocks[x][y][z];
+ M_Object *block_object = &game->block_atlas.blocks[block.type].obj;
+ M_moveObject(block_object, (vec3){(float)x, (float)y-32, (float)z});
+ M_drawObject(&game->render_info, &game->player.camera, block_object);
+ }
+}
diff --git a/src/engine/M_chunk.h b/src/engine/M_chunk.h
new file mode 100644
index 0000000..be1d4f1
--- /dev/null
+++ b/src/engine/M_chunk.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "M_object.h"
+#include "M_block.h"
+#include "M_game.h"
+
+#define M_CHUNK_SIZE 32
+
+
+typedef struct {
+ M_Block blocks[M_CHUNK_SIZE][M_CHUNK_SIZE][M_CHUNK_SIZE];
+ int x, y, z;
+} M_Chunk;
+
+void M_generateChunk(M_Chunk *chunk);
+
+void M_renderChunk(M_Game *game, M_Chunk *chunk);
diff --git a/src/engine/M_cube.c b/src/engine/M_cube.c
new file mode 100644
index 0000000..3be7417
--- /dev/null
+++ b/src/engine/M_cube.c
@@ -0,0 +1,39 @@
+#include "M_cube.h"
+
+M_ViewModel M_createCube()
+{
+ float vertices[] = {
+ 1.0f, 1.0f, -1.0f,
+ 1.0f, -1.0f, -1.0f,
+ -1.0f, -1.0f, -1.0f,
+ -1.0f, 1.0f, -1.0f,
+
+ 1.0f, 1.0f, 1.0f,
+ 1.0f, -1.0f, 1.0f,
+ -1.0f, -1.0f, 1.0f,
+ -1.0f, 1.0f, 1.0f
+ };
+ unsigned int indices[] = {
+ 0, 1, 2,
+ 0, 2, 3,
+
+ 4, 5, 6,
+ 4, 6, 7,
+
+ 0, 4, 5,
+ 2, 6, 3,
+
+ 3, 7, 6,
+ 1, 5, 0,
+
+ 3, 7, 0,
+ 0, 4, 7,
+
+ 2, 6, 1,
+ 1, 5, 6
+ };
+
+ M_ViewModel model;
+ M_createViewModel(&model, 8, vertices, 38, indices);
+ return model;
+}
diff --git a/src/engine/M_cube.h b/src/engine/M_cube.h
new file mode 100644
index 0000000..5c82901
--- /dev/null
+++ b/src/engine/M_cube.h
@@ -0,0 +1,4 @@
+#pragma once
+#include "M_object.h"
+
+M_ViewModel M_createCube();
diff --git a/src/engine/M_game.c b/src/engine/M_game.c
new file mode 100644
index 0000000..3c76d96
--- /dev/null
+++ b/src/engine/M_game.c
@@ -0,0 +1,66 @@
+#include "M_game.h"
+
+int M_initGame(M_Game *game, const char *window_title)
+{
+ game->window_width = 1280;
+ game->window_height = 720;
+
+ SDL_Init(
+ SDL_INIT_VIDEO
+ );
+
+ game->window = SDL_CreateWindow(
+ window_title,
+ game->window_width,
+ game->window_height,
+ SDL_WINDOW_OPENGL
+ );
+ M_setupProjection(90.0f, ((float)game->window_width)/((float)game->window_height), &game->render_info);
+
+ game->block_atlas = M_createBlockAtlas();
+
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ game->gpu = SDL_GL_CreateContext(game->window);
+
+ SDL_GL_MakeCurrent(game->window, game->gpu);
+
+ game->running = 1;
+
+ int version = gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress);
+ if (version == 0) {
+ return 1;
+ }
+
+ game->event_handler = SDL_CreateThread(M_handleEvents, "eventHandler", (void*)game);
+
+ glClearColor(0.0f, 0.25f, 0.5f, 1.0f);
+
+ glEnable(GL_DEPTH_TEST);
+
+ return 0;
+}
+
+int M_killGame(M_Game *game)
+{
+ SDL_WaitThread(game->event_handler, NULL);
+ SDL_Quit();
+ return 0;
+}
+
+int SDLCALL M_handleEvents(void* arg)
+{
+ M_Game *game = arg;
+ SDL_Event event;
+ while (game->running) {
+ SDL_PollEvent(&event);
+ switch (event.type) {
+ case SDL_EVENT_QUIT:
+ game->running = 0;
+ break;
+ }
+ SDL_Delay(1);
+ }
+ return 0;
+}
diff --git a/src/engine/M_game.h b/src/engine/M_game.h
new file mode 100644
index 0000000..a0b7942
--- /dev/null
+++ b/src/engine/M_game.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <SDL3/SDL_init.h>
+#include <SDL3/SDL_video.h>
+#include <SDL3/SDL_timer.h>
+
+#include <glad/gl.h>
+
+//#include "M_types.h"
+#include "M_render.h"
+#include "M_player.h"
+//#include "M_object.h"
+#include "M_block.h"
+
+typedef struct {
+ SDL_Window *window;
+ SDL_GLContext gpu;
+
+ int window_width, window_height;
+ int running;
+ M_RenderInfo render_info;
+
+ M_BlockAtlas block_atlas;
+
+ M_Player player;
+
+ SDL_Thread *event_handler;
+} M_Game;
+
+int M_initGame(M_Game *game, const char *window_title);
+int M_killGame(M_Game *game);
+
+int SDLCALL M_handleEvents(void* arg);
diff --git a/src/engine/M_main.c b/src/engine/M_main.c
new file mode 100644
index 0000000..93c186e
--- /dev/null
+++ b/src/engine/M_main.c
@@ -0,0 +1,48 @@
+#include <SDL3/SDL_video.h>
+
+#include "M_game.h"
+#include "M_object.h"
+#include "M_cube.h"
+#include "M_block.h"
+#include "M_chunk.h"
+
+int main()
+{
+ M_Game game;
+ M_initGame(&game, "MNM Engine");
+ M_initPlayer(&game.player);
+
+ M_ViewModel cube_model = M_createCube();
+
+ M_ShaderProgram my_shader = M_createShaderProgram(
+ "../src/shaders/test.vert",
+ "../src/shaders/test.frag"
+ );
+
+ M_Object my_cube;
+ M_createObject(&my_cube, &cube_model);
+ my_cube.shader = &my_shader;
+
+ M_scaleObject(&my_cube, (vec3){0.5f, 0.5, 0.5f});
+
+ M_createBlockType(my_cube, &game.block_atlas);
+
+ M_Chunk my_chunk;
+ M_generateChunk(&my_chunk);
+
+ M_moveObject(&my_cube, (vec3){0.0f, -0.5f, -1.0f});
+
+ M_bindViewModel(my_cube.model);
+
+ while (game.running) {
+ glClear(GL_COLOR_BUFFER_BIT);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ M_renderChunk(&game, &my_chunk);
+ SDL_GL_SwapWindow(game.window);
+ }
+
+ M_killShaderProgram(&my_shader);
+ M_killViewModel(&cube_model);
+ M_killGame(&game);
+ return 0;
+}
diff --git a/src/engine/M_object.c b/src/engine/M_object.c
new file mode 100644
index 0000000..07293d5
--- /dev/null
+++ b/src/engine/M_object.c
@@ -0,0 +1,108 @@
+#include "M_object.h"
+#include "M_camera.h"
+
+void M_createViewModel(M_ViewModel *model, int num_vertices, float *vert, int num_indices, unsigned int *indices)
+{
+ model->num_indices = num_indices;
+
+ glGenVertexArrays(1, &model->VAO);
+ glBindVertexArray(model->VAO);
+
+ glGenBuffers(1, &model->VBO);
+ glBindBuffer(GL_ARRAY_BUFFER, model->VBO);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float)*num_vertices*3, vert, GL_STATIC_DRAW);
+
+ glGenBuffers(1, &model->EBO);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->EBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*num_indices, indices, GL_STATIC_DRAW);
+
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
+ glEnableVertexAttribArray(0);
+}
+
+void M_killViewModel(M_ViewModel *model)
+{
+ glDeleteVertexArrays(1, &model->VAO);
+ glDeleteBuffers(1, &model->VBO);
+ glDeleteBuffers(1, &model->EBO);
+}
+
+M_ViewModel M_loadViewModel(const char* filename)
+{
+ const struct aiScene* scene = aiImportFile(filename,
+ aiProcess_CalcTangentSpace |
+ aiProcess_Triangulate |
+ aiProcess_JoinIdenticalVertices |
+ aiProcess_SortByPType);
+
+ struct aiMesh *mesh = scene->mMeshes[0];
+
+ unsigned int *indices = malloc(mesh->mNumFaces*3*sizeof(unsigned int));
+ int index = 0;
+ for (unsigned int i=0;i<mesh->mNumFaces;i++) {
+ memcpy(&indices[index], mesh->mFaces[i].mIndices, 3*sizeof(unsigned int));
+ index+=3;
+ }
+
+ M_ViewModel model;
+ M_createViewModel(&model, mesh->mNumVertices, (float*)mesh->mVertices, mesh->mNumFaces*3, indices);
+ free(indices);
+ return model;
+}
+
+void M_bindViewModel(M_ViewModel *model)
+{
+ glBindVertexArray(model->VAO);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->EBO);
+}
+
+
+void M_createObject(M_Object *obj, M_ViewModel *model)
+{
+ obj->model = model;
+ glm_mat4_identity(obj->transform);
+
+ glm_vec3_zero(obj->pos);
+ glm_vec3_one(obj->size);
+
+ obj->rotation.angle = 0.0f;
+ glm_vec3_zero(obj->rotation.direction);
+}
+
+void M_moveObject(M_Object *obj, vec3 pos)
+{
+ glm_vec3_copy(
+ pos,
+ obj->pos
+ );
+ M_updateObjectTransform(obj);
+}
+
+void M_scaleObject(M_Object *obj, vec3 scale)
+{
+ glm_vec3_copy(
+ scale,
+ obj->size
+ );
+ M_updateObjectTransform(obj);
+}
+
+void M_rotateObject(M_Object *obj, float angle, vec3 direction)
+{
+ obj->rotation.angle = angle;
+ glm_vec3_copy(
+ direction,
+ obj->rotation.direction
+ );
+ M_updateObjectTransform(obj);
+}
+
+inline void M_updateObjectTransform(M_Object *obj)
+{
+ glm_mat4_identity(obj->transform);
+ glm_translate(obj->transform, obj->pos);
+ glm_rotate(obj->transform, obj->rotation.angle, obj->rotation.direction);
+ glm_scale(obj->transform, obj->size);
+}
+
diff --git a/src/engine/M_object.h b/src/engine/M_object.h
new file mode 100644
index 0000000..ca87f0a
--- /dev/null
+++ b/src/engine/M_object.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <cglm/cglm.h>
+#include <cglm/mat4.h>
+#include <cglm/vec3.h>
+
+#include <assimp/cimport.h>
+#include <assimp/scene.h>
+#include <assimp/mesh.h>
+#include <assimp/postprocess.h>
+
+//#include "M_game.h"
+#include "M_shader.h"
+
+//Temporary type for storing M_Object rotation information,
+//will get replaced in later revisions.
+typedef struct {
+ float angle;
+ vec3 direction;
+} M_Rotation;
+
+//Stores information about a 3D model loaded in VRAM
+typedef struct {
+ int num_indices;
+
+ unsigned int VAO, VBO, EBO;
+} M_ViewModel;
+
+//Type meant for handling 3D models in a scene,
+//stores additional information like a model's position, size and rotation.
+typedef struct {
+ M_ViewModel *model;
+ M_ShaderProgram *shader;
+
+ vec3 pos, size;
+
+ M_Rotation rotation;
+
+ mat4 transform;
+} M_Object;
+
+//Creates a M_ViewModel out of vertices and indices manually
+void M_createViewModel(M_ViewModel *model, int num_vertices, float *vert, int num_indices, unsigned int *indices);
+
+//Unloads M_ViewModel from memory when no longer needed
+void M_killViewModel(M_ViewModel *model);
+
+//Loads and creates a M_ViewModel from a 3D object file like .obj
+M_ViewModel M_loadViewModel(const char* filename);
+
+//Creates a M_Object
+void M_createObject(M_Object *obj, M_ViewModel *model);
+
+
+//Functions for moving, scaling and rotating M_Object
+void M_moveObject(M_Object *obj, vec3 pos);
+void M_scaleObject(M_Object *obj, vec3 scale);
+void M_rotateObject(M_Object *obj, float angle, vec3 direction);
+
+//Updates M_Object transform matrix manually
+void M_updateObjectTransform(M_Object *obj);
+
+//Binds M_ViewModel for drawing
+void M_bindViewModel(M_ViewModel *model);
diff --git a/src/engine/M_player.c b/src/engine/M_player.c
new file mode 100644
index 0000000..1e065fd
--- /dev/null
+++ b/src/engine/M_player.c
@@ -0,0 +1,32 @@
+#include "M_player.h"
+
+void M_initPlayer(M_Player* player)
+{
+ glm_vec3_zero(player->pos);
+ M_initCamera(&player->camera, (vec3){0.0f, 1.0f, 0.0f});
+}
+
+void M_teleportPlayer(M_Player* player, vec3 pos)
+{
+ glm_vec3_copy(
+ pos,
+ player->pos
+ );
+ glm_vec3_copy(
+ pos,
+ player->camera.pos
+ );
+}
+
+void M_movePlayer(M_Player* player, vec3 pos)
+{
+ glm_vec3_add(
+ pos,
+ player->pos,
+ player->pos
+ );
+ glm_vec3_copy(
+ player->pos,
+ player->camera.pos
+ );
+}
diff --git a/src/engine/M_player.h b/src/engine/M_player.h
new file mode 100644
index 0000000..80856f8
--- /dev/null
+++ b/src/engine/M_player.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <cglm/vec3.h>
+
+#include "M_camera.h"
+
+typedef struct {
+ vec3 pos;
+ M_Camera camera;
+} M_Player;
+
+void M_initPlayer(M_Player* player);
+
+
+//void M_teleportPlayer(M_Player* player, vec3 pos)
+void M_movePlayer(M_Player* player, vec3 pos);
diff --git a/src/engine/M_render.c b/src/engine/M_render.c
new file mode 100644
index 0000000..1d83ceb
--- /dev/null
+++ b/src/engine/M_render.c
@@ -0,0 +1,17 @@
+#include "M_render.h"
+
+void M_setupProjection(float fov, float aspect_ratio, M_RenderInfo *render_info)
+{
+ glm_perspective(fov, aspect_ratio, 0.01f, 10.0f, render_info->projection_matrix);
+}
+
+void M_drawObject(M_RenderInfo *render_info, M_Camera *camera, M_Object *obj)
+{
+ glUseProgram(obj->shader->prog);
+ glUniformMatrix4fv(obj->shader->transform_loc, 1, GL_FALSE, (float*)obj->transform);
+ M_cameraViewMatrix(camera);
+ glUniformMatrix4fv(obj->shader->view_loc, 1, GL_FALSE, (float*)camera->view_matrix);
+ glUniformMatrix4fv(obj->shader->projection_loc, 1, GL_FALSE, (float*)render_info->projection_matrix);
+
+ glDrawElements(GL_TRIANGLES, obj->model->num_indices, GL_UNSIGNED_INT, 0);
+}
diff --git a/src/engine/M_render.h b/src/engine/M_render.h
new file mode 100644
index 0000000..948f0d5
--- /dev/null
+++ b/src/engine/M_render.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <cglm/cglm.h>
+#include <cglm/mat4.h>
+
+#include "M_object.h"
+#include "M_camera.h"
+
+typedef struct {
+ mat4 view_matrix, projection_matrix;
+} M_RenderInfo;
+
+void M_setupProjection(float fov, float aspect_ratio, M_RenderInfo *render_indo);
+
+//Draws M_Object in space
+void M_drawObject(M_RenderInfo *render_info, M_Camera *camera, M_Object *obj);
diff --git a/src/engine/M_shader.c b/src/engine/M_shader.c
new file mode 100644
index 0000000..17f6248
--- /dev/null
+++ b/src/engine/M_shader.c
@@ -0,0 +1,57 @@
+#include "M_shader.h"
+
+unsigned int M_loadShader(const char* filename, unsigned int shadertype)
+{
+ void* shader_source = SDL_LoadFile(filename, NULL);
+ unsigned int shader = glCreateShader(shadertype);
+ glShaderSource(shader, 1, (const char**)&shader_source, NULL);
+ glCompileShader(shader);
+ SDL_free(shader_source);
+
+ int success;
+
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ printf("Couldn't compile shader\n");
+ return 0;
+ }
+
+ return shader;
+}
+
+M_ShaderProgram M_createShaderProgram(const char *vertex_shader_file, const char* fragment_shader_file)
+{
+ unsigned int vertex_shader = M_loadShader(vertex_shader_file, GL_VERTEX_SHADER);
+ unsigned int fragment_shader = M_loadShader(fragment_shader_file, GL_FRAGMENT_SHADER);
+ return M_compileShaderProgram(vertex_shader, fragment_shader);
+}
+
+M_ShaderProgram M_compileShaderProgram(unsigned int vertex_shader, unsigned int fragment_shader)
+{
+ M_ShaderProgram shader_program;
+ shader_program.prog = glCreateProgram();
+ glAttachShader(shader_program.prog, vertex_shader);
+ glAttachShader(shader_program.prog, fragment_shader);
+ glLinkProgram(shader_program.prog);
+
+ shader_program.vertex_shader = vertex_shader;
+ shader_program.fragment_shader = fragment_shader;
+
+ int success;
+ glGetProgramiv(shader_program.prog, GL_LINK_STATUS, &success);
+ if (!success) {
+ printf("Couldn't link shader program\n");
+ }
+
+ shader_program.transform_loc = glGetUniformLocation(shader_program.prog, "model");
+ shader_program.view_loc = glGetUniformLocation(shader_program.prog, "view");
+ shader_program.projection_loc = glGetUniformLocation(shader_program.prog, "projection");
+
+ return shader_program;
+}
+
+void M_killShaderProgram(M_ShaderProgram *shader_program)
+{
+ glDeleteShader(shader_program->vertex_shader);
+ glDeleteShader(shader_program->fragment_shader);
+}
diff --git a/src/engine/M_shader.h b/src/engine/M_shader.h
new file mode 100644
index 0000000..0dbd170
--- /dev/null
+++ b/src/engine/M_shader.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <stdio.h>
+
+#include <SDL3/SDL_iostream.h>
+
+#include <glad/gl.h>
+
+typedef struct {
+ unsigned int prog;
+ unsigned int vertex_shader, fragment_shader;
+ unsigned int transform_loc, view_loc, projection_loc;
+} M_ShaderProgram;
+
+unsigned int M_loadShader(const char* filename, unsigned int shadertype);
+
+M_ShaderProgram M_createShaderProgram(const char *vertex_shader, const char* fragment_shader);
+
+M_ShaderProgram M_compileShaderProgram(unsigned int vertex_shader, unsigned int fragment_shader);
+
+void M_killShaderProgram(M_ShaderProgram *shader_program);
diff --git a/src/engine/M_types.h b/src/engine/M_types.h
new file mode 100644
index 0000000..cba3310
--- /dev/null
+++ b/src/engine/M_types.h
@@ -0,0 +1,10 @@
+#pragma once
+
+typedef struct M_Game;
+
+typedef struct M_ViewModel;
+typedef struct M_Object;
+
+typedef struct M_Block;
+typedef struct M_BlockType;
+typedef struct M_BlockAtlas;
diff --git a/src/shaders/basic.frag b/src/shaders/basic.frag
new file mode 100644
index 0000000..00d2a13
--- /dev/null
+++ b/src/shaders/basic.frag
@@ -0,0 +1,6 @@
+#version 330 core
+out vec4 FragColor;
+void main()
+{
+ FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
+}
diff --git a/src/shaders/basic.vert b/src/shaders/basic.vert
new file mode 100644
index 0000000..684ddbb
--- /dev/null
+++ b/src/shaders/basic.vert
@@ -0,0 +1,6 @@
+#version 330 core
+layout (location = 0) in vec3 aPos;
+void main()
+{
+ gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
+}
diff --git a/src/shaders/test.frag b/src/shaders/test.frag
new file mode 100644
index 0000000..38fd1f0
--- /dev/null
+++ b/src/shaders/test.frag
@@ -0,0 +1,17 @@
+#version 330 core
+
+out vec4 FragColor;
+
+in vec4 vertexColor;
+in vec4 lightColor;
+
+void main()
+{
+// float ambientStrength = 0.8;
+// vec3 lightColor = vec3(0.5, 0.5, 0.5);
+//
+// vec3 ambient = ambientStrength * lightColor;
+//
+// FragColor = vec4(ambient, 1.0) * vertexColor;
+ FragColor = vertexColor * lightColor;
+}
diff --git a/src/shaders/test.vert b/src/shaders/test.vert
new file mode 100644
index 0000000..e68611d
--- /dev/null
+++ b/src/shaders/test.vert
@@ -0,0 +1,19 @@
+#version 330 core
+
+layout (location = 0) in vec3 aPos;
+
+uniform mat4 model;
+uniform mat4 view;
+uniform mat4 projection;
+
+out vec4 vertexColor;
+out vec4 lightColor;
+
+void main()
+{
+ gl_Position = projection * view * model * vec4(aPos, 1.0);
+ vertexColor = vec4(0.0, 0.5, 0.0, 1.0);
+
+ lightColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);
+// lightColor = vec4(1.0,1.0,1.0,1.0);
+}