diff --git a/game/Makefile b/game/Makefile index e7cb608..67b93ed 100644 --- a/game/Makefile +++ b/game/Makefile @@ -1,7 +1,7 @@ SRC=src/main.c src/program.c src/resources.c src/camera.c src/chunk/chunk.c \ - src/chunk/mesh.c src/flags.c src/texture.c src/chunk/manager.c \ + src/chunk/chunkmesh.c src/flags.c src/texture.c src/chunk/chunkman.c \ src/event/manager.c src/event/handlers.c src/state.c src/graphics.c \ - src/entity/meshes.c src/entity/manager.c src/entity/templates.c + src/entity/meshes.c src/entity/entman.c src/entity/templates.c OBJ=$(SRC:.c=.o) CFLAGS=-g -pg -Werror -Wextra -Wall `pkg-config --cflags sdl3 sdl3-image cglm gl glib-2.0` diff --git a/game/res/textures/clouds.png b/game/res/textures/clouds.png new file mode 100644 index 0000000..53c5dd8 Binary files /dev/null and b/game/res/textures/clouds.png differ diff --git a/game/src/camera.c b/game/src/camera.c index e3c7e42..5321479 100644 --- a/game/src/camera.c +++ b/game/src/camera.c @@ -33,5 +33,5 @@ camera_get_view (mat4 dest) void camera_get_projection (float aspect, mat4 dest) { - glm_perspective (glm_rad (90), aspect, 0.1, 1000.0, dest); + glm_perspective (glm_rad (70), aspect, 0.01, 5000.0, dest); } diff --git a/game/src/chunk/manager.c b/game/src/chunk/chunkman.c similarity index 96% rename from game/src/chunk/manager.c rename to game/src/chunk/chunkman.c index 2486c20..140897a 100644 --- a/game/src/chunk/manager.c +++ b/game/src/chunk/chunkman.c @@ -1,4 +1,4 @@ -#include "manager.h" +#include "chunkman.h" /* TODO: perhaps render the chunks in a circle, not a square, around the player? */ @@ -6,6 +6,8 @@ static GHashTable *chunks; static GHashTable *chunk_meshes; +static bool bound = false; + guint chunkman_ivec2_hash (gconstpointer key) { @@ -55,7 +57,6 @@ chunkman_get_height_at (float x, float z) return 0.0; } - // Pozycja lokalna w chunku float lx = x - cx * CHUNK_DIM; float lz = z - cz * CHUNK_DIM; @@ -86,7 +87,7 @@ chunkman_get_height_at (float x, float z) else h11 = c ? c_get_height (c, 0, 0) : h00; - // Interpolacja + // Bilinear interpolation. float h0 = h00 * (1 - tx) + h10 * tx; float h1 = h01 * (1 - tx) + h11 * tx; float height = h0 * (1 - tz) + h1 * tz; @@ -146,11 +147,19 @@ chunkman_render (vec3 camera_position, int program) ChunkMesh *mesh = chunkman_get_ChunkMesh_at (x, z); if (mesh != NULL) { + if (!bound) + { + ChunkMesh_bind (mesh); + bound = true; + } + program_set_vec3 (program, "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM); ChunkMesh_render (mesh); } } - } + } + + bound = false; } Chunk * @@ -190,7 +199,7 @@ chunkman_generate_Chunk_at (int cx, int cz) tree->position[0] = x + xoffset; tree->position[1] = chunk->heightmap [INDEX (x, z)]; tree->position[2] = z + zoffset; - tree->rotation = rand () % 180; + tree->rotation[1] = rand () % 180; ENTADD (tree); } diff --git a/game/src/chunk/manager.h b/game/src/chunk/chunkman.h similarity index 93% rename from game/src/chunk/manager.h rename to game/src/chunk/chunkman.h index 8698643..9ef9708 100644 --- a/game/src/chunk/manager.h +++ b/game/src/chunk/chunkman.h @@ -4,9 +4,9 @@ #include #include "chunk.h" -#include "mesh.h" +#include "chunkmesh.h" #include "../program.h" -#include "../entity/manager.h" +#include "../entity/entman.h" #include "../entity/templates.h" #define RENDER_DISTANCE 3 diff --git a/game/src/chunk/mesh.c b/game/src/chunk/chunkmesh.c similarity index 95% rename from game/src/chunk/mesh.c rename to game/src/chunk/chunkmesh.c index 0827834..c642dec 100644 --- a/game/src/chunk/mesh.c +++ b/game/src/chunk/chunkmesh.c @@ -1,4 +1,4 @@ -#include "mesh.h" +#include "chunkmesh.h" /* No need to bind the elements buffer all the time; it's the same for every single ChunkMesh. */ @@ -84,9 +84,6 @@ ChunkMesh_build (Chunk *chunk, Chunk *nr, Chunk *nd, Chunk *nc) glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * CHUNK_SIZE * 6, indices, GL_STATIC_DRAW); - - glBindBuffer (GL_ARRAY_BUFFER, 0); - glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); free (positions); free (materials); @@ -95,6 +92,14 @@ ChunkMesh_build (Chunk *chunk, Chunk *nr, Chunk *nd, Chunk *nc) return mesh; } +void +ChunkMesh_bind (ChunkMesh *mesh) +/* The EBO is the same for all chunk meshes, so we can bind it just + once before we render them all. */ +{ + glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); +} + void ChunkMesh_render (ChunkMesh *mesh) { @@ -105,8 +110,6 @@ ChunkMesh_render (ChunkMesh *mesh) glBindBuffer (GL_ARRAY_BUFFER, mesh->mbo); glEnableVertexAttribArray (1); glVertexAttribPointer (1, 4, GL_FLOAT, GL_FALSE, sizeof (float) * 4, 0); - - glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); if (flags_get ("wireframe_enabled")) { diff --git a/game/src/chunk/mesh.h b/game/src/chunk/chunkmesh.h similarity index 92% rename from game/src/chunk/mesh.h rename to game/src/chunk/chunkmesh.h index ca38d9d..0772f88 100644 --- a/game/src/chunk/mesh.h +++ b/game/src/chunk/chunkmesh.h @@ -18,6 +18,7 @@ typedef struct ChunkMesh unsigned int ebo; } ChunkMesh; -/* Rename to ChunkMesh_build */ + ChunkMesh *ChunkMesh_build (Chunk *chunk, Chunk *nr, Chunk *nd, Chunk *nc); +void ChunkMesh_bind (ChunkMesh *mesh); void ChunkMesh_render (ChunkMesh *mesh); diff --git a/game/src/entity/entity.h b/game/src/entity/entity.h index e98a5a9..527acd3 100644 --- a/game/src/entity/entity.h +++ b/game/src/entity/entity.h @@ -7,17 +7,41 @@ typedef struct Entity { - enum { MESH_QUAD2, MESH_QUAD_X } mesh_type; + enum { MESH_QUAD1, MESH_QUAD2, MESH_QUAD_X } mesh_type; enum { ORIGIN_CENTER, ORIGIN_BOTTOM } origin; enum { RENDER_NORMAL, RENDER_BILLBOARD_Y, RENDER_BILLBOARD } render_type; bool visible; + bool dont_cull; void *userdata; void (*on_tick) (struct Entity *self); vec3 position; - float rotation; + vec3 rotation; vec3 scale; - char *texture; + /* Use RESTEX to get the int. */ + unsigned int texture; } Entity; + +static inline void +entity_compute_aabb (Entity *e, vec3 out_min, vec3 out_max) +{ + vec3 half = { 0.5f * e->scale[0], 0.5f * e->scale[1], 0.5f * e->scale[2] }; + + if (e->origin == ORIGIN_BOTTOM) + { + out_min[0] = e->position[0] - half[0]; + out_min[1] = e->position[1]; + out_min[2] = e->position[2] - half[2]; + + out_max[0] = e->position[0] + half[0]; + out_max[1] = e->position[1] + e->scale[1]; + out_max[2] = e->position[2] + half[2]; + } + else + { + glm_vec3_sub (e->position, half, out_min); + glm_vec3_add (e->position, half, out_max); + } +} diff --git a/game/src/entity/manager.c b/game/src/entity/entman.c similarity index 75% rename from game/src/entity/manager.c rename to game/src/entity/entman.c index 014a53a..62486d9 100644 --- a/game/src/entity/manager.c +++ b/game/src/entity/entman.c @@ -1,14 +1,13 @@ -#include "manager.h" +#include "entman.h" extern vec3 camera_position; Entity *player_entity; static GSequence *entities; -static EntityMesh mesh_quad2, mesh_quad_x; +static EntityMesh mesh_quad1, mesh_quad2, mesh_quad_x; static unsigned int last_type = -1; - -#define CULL_FRUSTUM 0 +static unsigned int last_texture = -1; void character_on_tick (Entity *entity) @@ -20,6 +19,7 @@ void entman_init () { entities = g_sequence_new (NULL); + mesh_quad1 = EntityMesh_make_quad1 (); mesh_quad2 = EntityMesh_make_quad2 (); mesh_quad_x = EntityMesh_make_quad_x (); @@ -28,12 +28,25 @@ entman_init () .origin = ORIGIN_BOTTOM, .visible = false, .position = { 0.0 }, - .rotation = 0.0, .scale = { 1.0, 1.8, 1.0 }, .on_tick = character_on_tick }; ENTADD (player_entity); + + Entity *sky = malloc (sizeof (Entity)); + *sky = (Entity) { + .mesh_type = MESH_QUAD1, + .origin = ORIGIN_CENTER, + .visible = true, + .dont_cull = true, + .position = { 0.0, 200.0, 0.0 }, + .scale = { 5000.0, 5000.0, 5000.0 }, + .rotation = { 90.0 }, + .texture = RESTEX ("clouds") + }; + + ENTADD (sky); } void @@ -65,7 +78,8 @@ entman_render_internal (gpointer data, gpointer userdata) return; } - if (glm_vec3_distance (camera_position, entity->position) > ENTITY_RENDER_DISTANCE) + if (glm_vec3_distance (camera_position, entity->position) > ENTITY_RENDER_DISTANCE + && !entity->dont_cull) { return; } @@ -73,8 +87,7 @@ entman_render_internal (gpointer data, gpointer userdata) /* TODO: Fix this up. It still isn't perfect, when you look up, sometimes the entities get culled. */ - #if CULL_FRUSTUM - +#if FRUSTUM_CULL vec4 planes[6]; mat4 proj, view_proj; @@ -82,29 +95,26 @@ entman_render_internal (gpointer data, gpointer userdata) glm_mat4_mul (proj, *view, view_proj); glm_frustum_planes (view_proj, planes); - vec3 aabb[2] = { - { -entity->scale[0] + entity->position[0], - -entity->scale[1] + entity->position[1] + (entity->origin == ORIGIN_BOTTOM ? entity->scale[1] : 0), - -entity->scale[2] + entity->position[2] }, - { +entity->scale[0] + entity->position[0], - +entity->scale[1] + entity->position[1] + (entity->origin == ORIGIN_BOTTOM ? entity->scale[1] : 0), - +entity->scale[2] + entity->position[2] }, - }; + vec3 aabb[2]; + entity_compute_aabb (entity, aabb[0], aabb[1]); if (!glm_aabb_frustum (aabb, planes)) { return; } - - #endif +#endif EntityMesh to_render; + unsigned int render_type = entity->render_type; switch (entity->mesh_type) { case MESH_QUAD_X: to_render = mesh_quad_x; break; + case MESH_QUAD1: + to_render = mesh_quad1; + break; default: to_render = mesh_quad2; break; @@ -112,7 +122,7 @@ entman_render_internal (gpointer data, gpointer userdata) mat4 model = GLM_MAT4_IDENTITY_INIT; - switch (entity->render_type) + switch (render_type) { case RENDER_BILLBOARD: mat4 inv_view; @@ -145,7 +155,9 @@ entman_render_internal (gpointer data, gpointer userdata) glm_translate (model, entity->position); break; default: - glm_rotate_at (model, entity->position, glm_rad (entity->rotation), (vec3) { 0.0, 1.0, 0.0 }); + glm_rotate_at (model, entity->position, glm_rad (entity->rotation[0]), (vec3) { 1.0, 0.0, 0.0 }); + glm_rotate_at (model, entity->position, glm_rad (entity->rotation[1]), (vec3) { 0.0, 1.0, 0.0 }); + glm_rotate_at (model, entity->position, glm_rad (entity->rotation[2]), (vec3) { 0.0, 0.0, 1.0 }); glm_translate (model, entity->position); break; } @@ -159,10 +171,10 @@ entman_render_internal (gpointer data, gpointer userdata) program_set_mat4 (RESPRG ("default"), "model", model); - if (entity->texture != NULL) + if (entity->texture != last_texture) { glActiveTexture (GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, RESTEX (entity->texture)); + glBindTexture (GL_TEXTURE_2D, entity->texture); } if (entity->mesh_type != last_type) @@ -171,6 +183,7 @@ entman_render_internal (gpointer data, gpointer userdata) } last_type = entity->mesh_type; + last_texture = entity->texture; EntityMesh_render (&to_render); } @@ -194,16 +207,19 @@ entman_compare (gconstpointer a, gconstpointer b, gpointer userdata) return 0; } + // Handle MESH_QUAD1 + if (entity1->mesh_type == MESH_QUAD1) + return -1; + if (entity2->mesh_type == MESH_QUAD1) + return 1; + + // Handle MESH_QUAD_X vs MESH_QUAD2 if (entity1->mesh_type == MESH_QUAD_X && entity2->mesh_type == MESH_QUAD2) - { - return -1; - } - + return -1; if (entity1->mesh_type == MESH_QUAD2 && entity2->mesh_type == MESH_QUAD_X) - { - return 1; - } + return 1; + // Default: compare numerically return (int) entity1->mesh_type - (int) entity2->mesh_type; } diff --git a/game/src/entity/manager.h b/game/src/entity/entman.h similarity index 74% rename from game/src/entity/manager.h rename to game/src/entity/entman.h index 2ced55d..d610247 100644 --- a/game/src/entity/manager.h +++ b/game/src/entity/entman.h @@ -8,9 +8,10 @@ #include "../util.h" #include "../resources.h" #include "../state.h" -#include "../chunk/manager.h" +#include "../chunk/chunkman.h" -#define ENTITY_RENDER_DISTANCE (3*CHUNK_DIM/2) +#define ENTITY_RENDER_DISTANCE (RENDER_DISTANCE*CHUNK_DIM) +#define FRUSTUM_CULL 1 #define ENTADD(entity) (entman_add_entity (entity)) diff --git a/game/src/entity/meshes.c b/game/src/entity/meshes.c index 67a9f39..ecb25de 100644 --- a/game/src/entity/meshes.c +++ b/game/src/entity/meshes.c @@ -32,6 +32,51 @@ EntityMesh_render (EntityMesh *mesh) } } +EntityMesh +EntityMesh_make_quad1 () +{ + /* The positions are trivial. */ + float positions[12] = { + -1.0, -1.0, 0.0, + +1.0, -1.0, 0.0, + -1.0, 1.0, 0.0, + +1.0, 1.0, 0.0 + }; + + unsigned int indices[12] = { + 3, 2, 0, 0, 1, 3, + }; + + float uvs[8] = { + 0.0, 1.0, + 1.0, 1.0, + 0.0, 0.0, + 1.0, 0.0, + }; + + EntityMesh mesh; + mesh.indices_len = 6; + glGenBuffers (1, &mesh.pbo); + glGenBuffers (1, &mesh.uvbo); + glGenBuffers (1, &mesh.ebo); + + glBindBuffer (GL_ARRAY_BUFFER, mesh.pbo); + glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 12, positions, GL_STATIC_DRAW); + glEnableVertexAttribArray (0); + glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (float) * 3, 0); + + glBindBuffer (GL_ARRAY_BUFFER, mesh.uvbo); + glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 8, uvs, GL_STATIC_DRAW); + glEnableVertexAttribArray (1); + glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, sizeof (float) * 2, 0); + + + glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh.ebo); + glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * mesh.indices_len, indices, GL_STATIC_DRAW); + + return mesh; +} + EntityMesh EntityMesh_make_quad2 () { @@ -75,9 +120,6 @@ EntityMesh_make_quad2 () glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh.ebo); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * mesh.indices_len, indices, GL_STATIC_DRAW); - glBindBuffer (GL_ARRAY_BUFFER, 0); - glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - return mesh; } @@ -135,8 +177,5 @@ EntityMesh_make_quad_x () glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh.ebo); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * mesh.indices_len, indices, GL_STATIC_DRAW); - glBindBuffer (GL_ARRAY_BUFFER, 0); - glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - return mesh; } diff --git a/game/src/entity/meshes.h b/game/src/entity/meshes.h index 0959c8d..4cd03e1 100644 --- a/game/src/entity/meshes.h +++ b/game/src/entity/meshes.h @@ -15,5 +15,6 @@ typedef struct EntityMesh void EntityMesh_bind (EntityMesh *mesh); void EntityMesh_render (EntityMesh *mesh); +EntityMesh EntityMesh_make_quad1 (); EntityMesh EntityMesh_make_quad2 (); EntityMesh EntityMesh_make_quad_x (); diff --git a/game/src/entity/templates.c b/game/src/entity/templates.c index 2b3e142..0e67b66 100644 --- a/game/src/entity/templates.c +++ b/game/src/entity/templates.c @@ -24,24 +24,24 @@ ent_templates_init () .mesh_type = MESH_QUAD_X, .visible = true, .origin = ORIGIN_BOTTOM, - .position = { 0.0, 0.0, 0.0 }, + .position = { 0.0 }, .scale = { 3.0, 8.0, 3.0 }, - .rotation = 0.0, - .texture = "tree0" + .rotation = { 0.0 }, + .texture = RESTEX ("tree0") }; ent_templates_add ("tree", tree); Entity *grass = malloc (sizeof (Entity)); *grass = (Entity) { - .mesh_type = MESH_QUAD2, + .mesh_type = MESH_QUAD1, .render_type = RENDER_BILLBOARD_Y, .visible = true, .origin = ORIGIN_BOTTOM, - .position = { 0.0, 0.0, 0.0 }, + .position = { 0.0 }, .scale = { 1.0, 0.5, 1.0 }, - .rotation = 0.0, - .texture = "grass0" + .rotation = { 0.0 }, + .texture = RESTEX ("grass0") }; ent_templates_add ("grass", grass); diff --git a/game/src/entity/templates.h b/game/src/entity/templates.h index d30e2f3..f8fee39 100644 --- a/game/src/entity/templates.h +++ b/game/src/entity/templates.h @@ -6,6 +6,7 @@ #include #include "entity.h" +#include "../resources.h" #define ETEMPLGET(key) (ent_templates_get (key)) diff --git a/game/src/graphics.c b/game/src/graphics.c index 3339a3b..1b207f5 100644 --- a/game/src/graphics.c +++ b/game/src/graphics.c @@ -71,10 +71,9 @@ graphics_render () glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain3")); glActiveTexture (GL_TEXTURE4); glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain4")); - + chunkman_render (camera_position, RESPRG ("chunk")); - /* Set views and projections in all programs. TODO: make this dynamic*/ program_use (RESPRG ("default")); program_set_mat4 (RESPRG ("default"), "projection", projection); program_set_mat4 (RESPRG ("default"), "view", view); diff --git a/game/src/graphics.h b/game/src/graphics.h index 916730a..4ff3a70 100644 --- a/game/src/graphics.h +++ b/game/src/graphics.h @@ -4,8 +4,8 @@ #include #include "util.h" -#include "chunk/manager.h" -#include "entity/manager.h" +#include "chunk/chunkman.h" +#include "entity/entman.h" #include "state.h" #include "resources.h" diff --git a/game/src/main.c b/game/src/main.c index 3d03c24..e08a691 100644 --- a/game/src/main.c +++ b/game/src/main.c @@ -5,7 +5,7 @@ #include "event/manager.h" #include "event/handlers.h" -#include "chunk/manager.h" +#include "chunk/chunkman.h" #include "entity/templates.h" #include "state.h" #include "resources.h" diff --git a/game/src/resources.c b/game/src/resources.c index 7f2b681..c3095fa 100644 --- a/game/src/resources.c +++ b/game/src/resources.c @@ -96,6 +96,12 @@ resources_init () RAT ("terrain4", RLT ("res/textures/asphalt_gravel.png")); RAT ("tree0", RLT ("res/textures/tree.png")); RAT ("grass0", RLT ("res/textures/grass0.png")); + RAT ("clouds", RLT ("res/textures/clouds.png")); + + #undef RAP + #undef RLP + #undef RAT + #undef RLP program_use (RESPRG ("chunk")); program_set_int_array (RESPRG ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });