diff --git a/game/res/textures/font.png b/game/res/textures/font.png index 6f41349..8894eba 100644 Binary files a/game/res/textures/font.png and b/game/res/textures/font.png differ diff --git a/game/res/textures/font.xcf b/game/res/textures/font.xcf index 675334b..8aa028a 100644 Binary files a/game/res/textures/font.xcf and b/game/res/textures/font.xcf differ diff --git a/game/src/chunk/chunkman.c b/game/src/chunk/chunkman.c index a67fe09..cfe3612 100644 --- a/game/src/chunk/chunkman.c +++ b/game/src/chunk/chunkman.c @@ -1,11 +1,17 @@ #include "chunkman.h" +/* TODO: Lots of entities are generated per-chunk. Perhaps adding them + to a queue would be better. */ + +/* TODO: Add queues regardless. */ + int n_frame_chunks; static GHashTable *chunks; static GHashTable *chunk_meshes; static bool bound = false; +static int frame_chunks = 0; guint chunkman_ivec2_hash (gconstpointer key) @@ -108,6 +114,7 @@ chunkman_tick (vec3 position) chunkman_world_to_chunk (position[0], position[2], &cx, &cz); unsigned int frame_time = SDL_GetTicks (); + frame_chunks = 0; for (int z = cz - RENDER_DISTANCE - 1; z <= cz + RENDER_DISTANCE + 1; ++z) { @@ -115,12 +122,13 @@ chunkman_tick (vec3 position) { if ((x - cx) * (x - cx) + (z - cz) * (z - cz) <= (RENDER_DISTANCE + 1) * (RENDER_DISTANCE + 1)) { - if (chunkman_get_Chunk_at (x, z) == NULL) + if (chunkman_get_Chunk_at (x, z) == NULL) { chunkman_generate_Chunk_at (x, z); + ++frame_chunks; } - if (SDL_GetTicks () - frame_time > FRAME_BUDGET) + if (frame_chunks > CHUNKS_PER_FRAME || SDL_GetTicks () - frame_time > FRAME_BUDGET) { return; } @@ -137,9 +145,10 @@ chunkman_tick (vec3 position) if (chunkman_get_ChunkMesh_at (x, z) == NULL) { chunkman_generate_ChunkMesh_at (x, z); + ++frame_chunks; } - if (SDL_GetTicks () - frame_time > FRAME_BUDGET) + if (frame_chunks > CHUNKS_PER_FRAME || SDL_GetTicks () - frame_time > FRAME_BUDGET) { return; } diff --git a/game/src/chunk/chunkman.h b/game/src/chunk/chunkman.h index 491ef16..00d477b 100644 --- a/game/src/chunk/chunkman.h +++ b/game/src/chunk/chunkman.h @@ -13,7 +13,8 @@ #define RENDER_DISTANCE 5 #define RENDER_SQR (RENDER_DISTANCE*RENDER_DISTANCE) #define TERRAIN_HEIGHT 8.0 -#define FRAME_BUDGET 3 +#define FRAME_BUDGET 5 +#define CHUNKS_PER_FRAME 1 void chunkman_init (); void chunkman_tick (vec3 position); diff --git a/game/src/entity/entity.h b/game/src/entity/entity.h index b9f7d8e..d4e288a 100644 --- a/game/src/entity/entity.h +++ b/game/src/entity/entity.h @@ -33,21 +33,23 @@ typedef struct 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] }; - + // The half extent is 1.0f, in that the mesh goes from -1 to 1. + vec3 half = { e->scale[0] * 1.0f, e->scale[1] * 1.0f, e->scale[2] * 1.0f }; + + out_min[0] = e->position[0] - half[0]; + out_max[0] = e->position[0] + half[0]; + 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]; - } + { + out_min[1] = e->position[1]; + out_max[1] = e->position[1] + 2.0f * half[1]; + } else - { - glm_vec3_sub (e->position, half, out_min); - glm_vec3_add (e->position, half, out_max); - } + { + out_min[1] = e->position[1] - half[1]; + out_max[1] = e->position[1] + half[1]; + } + + out_min[2] = e->position[2] - half[2]; + out_max[2] = e->position[2] + half[2]; } diff --git a/game/src/entity/entman.c b/game/src/entity/entman.c index 301caec..8d695be 100644 --- a/game/src/entity/entman.c +++ b/game/src/entity/entman.c @@ -14,7 +14,7 @@ int n_frame_ents; /* The GArray is the fastest of all sequence types. Should work fine for a billion entities. */ static GArray *entities; -static SimpleMesh mesh_quad1, mesh_quad2, mesh_quad_x; +static SimpleMesh mesh_quad1, mesh_quad2, mesh_quad_x, mesh_cube; static unsigned int last_program = -1; static unsigned int last_type = -1; static unsigned int last_texture = -1; @@ -32,6 +32,7 @@ entman_init () mesh_quad1 = SimpleMesh_make_quad1 (); mesh_quad2 = SimpleMesh_make_quad2 (); mesh_quad_x = SimpleMesh_make_quad_x (); + mesh_cube = SimpleMesh_make_cube (); player_entity = malloc (sizeof (Entity)); *player_entity = (Entity) { @@ -88,9 +89,10 @@ entman_render_entity (Entity *entity, void *userdata) { return; } + + float cull_dist = entity->cull_distance * RENDER_DISTANCE * CHUNK_DIM; - if (glm_vec3_distance (camera_position, entity->position) - > entity->cull_distance * RENDER_DISTANCE * CHUNK_DIM && !entity->dont_cull) + if (glm_vec3_distance2 (camera_position, entity->position) > glm_pow2 (cull_dist) && !entity->dont_cull) { return; } @@ -101,7 +103,7 @@ entman_render_entity (Entity *entity, void *userdata) #if FRUSTUM_CULL vec3 aabb[2]; entity_compute_aabb (entity, aabb[0], aabb[1]); - + if (!glm_aabb_frustum (aabb, *vp->frustum_planes)) { return; @@ -200,6 +202,17 @@ entman_render_entity (Entity *entity, void *userdata) n_frame_ents++; } +static inline int +entman_compare (gconstpointer a, gconstpointer b) +/* This function is used to sort Entities by their mesh type, so that + diferrent buffers aren't bound every single frame. */ +{ + const Entity *entity1 = a; + const Entity *entity2 = b; + + return (int) entity1->mesh_type - (int) entity2->mesh_type; +} + void entman_render (mat4 *view, vec4 planes[6]) { @@ -224,6 +237,9 @@ entman_render (mat4 *view, vec4 planes[6]) #endif }; + /* Sort entities by mesh type. */ + g_array_sort (entities, entman_compare); + for (guint i = 0; i < entities->len; ++i) { Entity *e = g_array_index (entities, Entity*, i); @@ -231,17 +247,6 @@ entman_render (mat4 *view, vec4 planes[6]) } } -static inline int -entman_compare (gconstpointer a, gconstpointer b) -/* This function is used to sort Entities by their mesh type, so that - diferrent buffers aren't bound every single frame. */ -{ - const Entity *entity1 = a; - const Entity *entity2 = b; - - return (int) entity1->mesh_type - (int) entity2->mesh_type; -} - void entman_add_entity (Entity *entity) { diff --git a/game/src/gl/mesh.c b/game/src/gl/mesh.c index 22c0cd5..cc2ebb0 100644 --- a/game/src/gl/mesh.c +++ b/game/src/gl/mesh.c @@ -179,3 +179,61 @@ SimpleMesh_make_quad_x () return mesh; } + +SimpleMesh +SimpleMesh_make_cube () +{ + /* The positions are trivial. */ + float positions[24] = { + -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[36] = { + 4, 5, 6, 6, 7, 4, + 0, 3, 2, 2, 1, 0, + 0, 4, 7, 7, 3, 0, + 1, 2, 6, 6, 5, 1, + 0, 1, 5, 5, 4, 0, + 3, 7, 6, 6, 2, 3 + }; + + float uvs[16] = { + 0.0, 1.0, + 1.0, 1.0, + 0.0, 0.0, + 1.0, 0.0, + + 0.0, 1.0, + 1.0, 1.0, + 0.0, 0.0, + 1.0, 0.0 + }; + + SimpleMesh mesh; + mesh.indices_len = 36; + glGenBuffers (1, &mesh.pbo); + glGenBuffers (1, &mesh.uvbo); + glGenBuffers (1, &mesh.ebo); + + glBindBuffer (GL_ARRAY_BUFFER, mesh.pbo); + glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 24, 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) * 16, 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; +} diff --git a/game/src/gl/mesh.h b/game/src/gl/mesh.h index 55bf4cc..ef4ceee 100644 --- a/game/src/gl/mesh.h +++ b/game/src/gl/mesh.h @@ -19,4 +19,4 @@ void SimpleMesh_render (SimpleMesh *mesh); SimpleMesh SimpleMesh_make_quad1 (); SimpleMesh SimpleMesh_make_quad2 (); SimpleMesh SimpleMesh_make_quad_x (); - +SimpleMesh SimpleMesh_make_cube (); diff --git a/game/src/resources.c b/game/src/resources.c index 8782c26..b70495c 100644 --- a/game/src/resources.c +++ b/game/src/resources.c @@ -152,7 +152,7 @@ resources_init () RAP ("chunk", RLP ("res/shaders/chunk.vert", "res/shaders/chunk.frag")); RAP ("clouds", RLP ("res/shaders/clouds.vert", "res/shaders/clouds.frag")); RAP ("uielement", RLP ("res/shaders/uielement.vert", "res/shaders/uielement.frag")); - + RAT ("terrain0", RLT ("res/textures/dirt.png")); RAT ("terrain1", RLT ("res/textures/drygrass.png")); RAT ("terrain2", RLT ("res/textures/grass.png")); @@ -167,7 +167,7 @@ resources_init () #undef RAP #undef RLP #undef RAT - #undef RLP + #undef RLT program_use (RESPRG ("chunk")); program_set_int_array (RESPRG ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });