diff --git a/game/res/shaders/default.vert b/game/res/shaders/default.vert index b539105..51b7213 100644 --- a/game/res/shaders/default.vert +++ b/game/res/shaders/default.vert @@ -1,5 +1,8 @@ #version 100 +/* Be aware of the fact that we are indeed sending three integers for + the position and two for the UV. None of the data is floating + point. */ attribute vec4 position; attribute vec2 uv; diff --git a/game/res/textures/font.png b/game/res/textures/font.png index 141349e..a346417 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 24de64b..4ab5815 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 1f016f0..6d24e4e 100644 --- a/game/src/chunk/chunkman.c +++ b/game/src/chunk/chunkman.c @@ -3,6 +3,8 @@ /* TODO: Sort chunks by distance to player, and generate them like that. Will require having a queue or similar structure. */ +extern int render_distance; + int n_frame_chunks; static GHashTable *chunks; @@ -114,9 +116,9 @@ chunkman_tick (vec3 position) uint64_t freq = SDL_GetPerformanceFrequency (); double elapsed_us = 0; - for (int z = cz - RENDER_DISTANCE - 1; z <= cz + RENDER_DISTANCE + 1; ++z) + for (int z = cz - render_distance - 1; z <= cz + render_distance + 1; ++z) { - for (int x = cx - RENDER_DISTANCE - 1; x <= cx + RENDER_DISTANCE + 1; ++x) + for (int x = cx - render_distance - 1; x <= cx + render_distance + 1; ++x) { uint64_t now = SDL_GetPerformanceCounter (); elapsed_us = (double) (now - start) * 1000000.0 / (double) freq; @@ -133,9 +135,9 @@ chunkman_tick (vec3 position) } } - for (int z = cz - RENDER_DISTANCE; z <= cz + RENDER_DISTANCE; ++z) + for (int z = cz - render_distance; z <= cz + render_distance; ++z) { - for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x) + for (int x = cx - render_distance; x <= cx + render_distance; ++x) { uint64_t now = SDL_GetPerformanceCounter (); elapsed_us = (double) (now - start) * 1000000.0 / (double) freq; @@ -178,39 +180,34 @@ chunkman_render (vec3 position, vec4 planes[6]) n_frame_chunks = 0; - for (int z = cz - RENDER_DISTANCE; z <= cz + RENDER_DISTANCE; ++z) + for (int z = cz - render_distance; z <= cz + render_distance; ++z) { - for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x) + for (int x = cx - render_distance; x <= cx + render_distance; ++x) { - if ((x - cx) * (x - cx) + (z - cz) * (z - cz) <= RENDER_SQR) + ChunkMesh *mesh = chunkman_get_ChunkMesh_at (x, z); + if (mesh != NULL) { - ChunkMesh *mesh = chunkman_get_ChunkMesh_at (x, z); - if (mesh != NULL) - { - /* This, compared to the entity AABB, seems to work - completely fine. */ #if FRUSTUM_CULL - vec3 aabb[2] = { - { x * CHUNK_DIM, 0.0, z * CHUNK_DIM }, - { (x + 1) * CHUNK_DIM, TERRAIN_HEIGHT, (z + 1) * CHUNK_DIM } - }; + vec3 aabb[2] = { + { x * CHUNK_DIM, 0.0, z * CHUNK_DIM }, + { (x + 1) * CHUNK_DIM, TERRAIN_HEIGHT, (z + 1) * CHUNK_DIM } + }; - if (!glm_aabb_frustum (aabb, planes)) - { - continue; - } + if (!glm_aabb_frustum (aabb, planes)) + { + continue; + } #endif - if (!bound) - { - ChunkMesh_bind (mesh); - bound = true; - } - - program_set_vec3_ind (RESPRG ("chunk"), "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM); - ChunkMesh_render (mesh, flags_get ("wireframe_enabled")); - n_frame_chunks++; + if (!bound) + { + ChunkMesh_bind (mesh); + bound = true; } + + program_set_vec3_ind (RESPRG ("chunk"), "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM); + ChunkMesh_render (mesh, flags_get ("wireframe_enabled")); + n_frame_chunks++; } } } diff --git a/game/src/chunk/chunkman.h b/game/src/chunk/chunkman.h index 25bd465..870d9a3 100644 --- a/game/src/chunk/chunkman.h +++ b/game/src/chunk/chunkman.h @@ -9,10 +9,7 @@ #include "../entity/entman.h" #include "../graphics.h" -#define RENDER_DISTANCE 5 -#define RENDER_SQR (RENDER_DISTANCE*RENDER_DISTANCE) #define TERRAIN_HEIGHT 8.0 -#define CHUNK_FRAME_BUDGET_US 100 void chunkman_init (); void chunkman_tick (vec3 position); diff --git a/game/src/entity/entman.c b/game/src/entity/entman.c index 90564ab..bf0c032 100644 --- a/game/src/entity/entman.c +++ b/game/src/entity/entman.c @@ -7,6 +7,7 @@ seperately somehow. */ extern vec3 camera_position; +extern int render_distance; Entity *player_entity, *sky_entity; int n_frame_ents; @@ -16,7 +17,7 @@ int n_frame_ents; static GArray *entities; static GQueue *spawn_requests; -static SimpleMesh mesh_quad1, mesh_quad2, mesh_quad_x, mesh_cube; +static SimpleMesh mesh_quad1, mesh_quad2, mesh_quad_x; static unsigned int last_program = -1; static unsigned int last_type = -1; static unsigned int last_texture = -1; @@ -38,7 +39,6 @@ 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 = Entity_new (); player_entity->visible = false; @@ -89,7 +89,9 @@ entman_tick () elapsed_us = (double) (now - start) * 1000000.0 / (double) freq; if (elapsed_us > ENTITY_FRAME_BUDGET_US) - break; + { + break; + } spawn_queue_process_one (); } @@ -121,11 +123,18 @@ entman_render_entity (Entity *entity, void *userdata) return; } - unsigned int cull_dist = RENDER_DISTANCE * CHUNK_DIM * (100 / entity->cull_distance); + /* Why an int, why int division? It's simply much faster than + floating point operations. No need to have super accurate cull + distance anyway, and might as well save a lot when rendering entities. */ + unsigned int cull_dist = (render_distance * CHUNK_DIM * entity->cull_distance) / 100; + /* Underneath is the slowest (for the CPU) part of the entity render + process. Moving the camera positions from memory into some + registers. Thus the entity rendering function optimization is + finished, as the last bottleneck is the amount of entities. */ vec2 c_xz = { camera_position[0], camera_position[2] }; vec2 e_xz = { entity->position[0], entity->position[2] }; - if (glm_vec2_distance2 (c_xz, e_xz) > glm_pow2 (cull_dist) && !entity->dont_cull) + if (glm_vec2_distance2 (c_xz, e_xz) > cull_dist*cull_dist && !entity->dont_cull) { return; } diff --git a/game/src/entity/entman.h b/game/src/entity/entman.h index dc18810..37d22a3 100644 --- a/game/src/entity/entman.h +++ b/game/src/entity/entman.h @@ -17,8 +17,6 @@ #define ENTADD(entity) (entman_add_entity (entity)) -#define ENTITY_FRAME_BUDGET_US 100 - typedef struct SpawnRequest { char *template_name; diff --git a/game/src/gl/mesh.c b/game/src/gl/mesh.c index 219ee2e..a4c31ed 100644 --- a/game/src/gl/mesh.c +++ b/game/src/gl/mesh.c @@ -5,16 +5,19 @@ OpenGL function, glVertexAttrib, that repeats the attribute for every subsequent vertex. */ +/* Every vertex attribute here is an int. This is to save GPU time or + some shit. Idk. But we don't need floats anyway. */ + void SimpleMesh_bind (SimpleMesh *mesh) { glBindBuffer (GL_ARRAY_BUFFER, mesh->pbo); glEnableVertexAttribArray (0); - glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (float) * 3, 0); + glVertexAttribPointer (0, 3, GL_INT, GL_FALSE, sizeof (int) * 3, 0); glBindBuffer (GL_ARRAY_BUFFER, mesh->uvbo); glEnableVertexAttribArray (1); - glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, sizeof (float) * 2, 0); + glVertexAttribPointer (1, 2, GL_INT, GL_FALSE, sizeof (int) * 2, 0); glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); } @@ -29,22 +32,22 @@ SimpleMesh SimpleMesh_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 + int positions[12] = { + -1, -1, 0, + +1, -1, 0, + -1, 1, 0, + +1, 1, 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, + int uvs[8] = { + 0, 1, + 1, 1, + 0, 0, + 1, 0, }; SimpleMesh mesh; @@ -54,15 +57,14 @@ SimpleMesh_make_quad1 () glGenBuffers (1, &mesh.ebo); glBindBuffer (GL_ARRAY_BUFFER, mesh.pbo); - glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 12, positions, GL_STATIC_DRAW); + glBufferData (GL_ARRAY_BUFFER, sizeof (int) * 12, positions, GL_STATIC_DRAW); glEnableVertexAttribArray (0); - glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (float) * 3, 0); + glVertexAttribPointer (0, 3, GL_INT, GL_FALSE, sizeof (int) * 3, 0); glBindBuffer (GL_ARRAY_BUFFER, mesh.uvbo); - glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 8, uvs, GL_STATIC_DRAW); + glBufferData (GL_ARRAY_BUFFER, sizeof (int) * 8, uvs, GL_STATIC_DRAW); glEnableVertexAttribArray (1); - glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, sizeof (float) * 2, 0); - + glVertexAttribPointer (1, 2, GL_INT, GL_FALSE, sizeof (int) * 2, 0); glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh.ebo); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * mesh.indices_len, indices, GL_STATIC_DRAW); @@ -74,11 +76,11 @@ SimpleMesh SimpleMesh_make_quad2 () { /* 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 + int positions[12] = { + -1, -1, 0, + +1, -1, 0, + -1, 1, 0, + +1, 1, 0 }; unsigned int indices[12] = { @@ -86,11 +88,11 @@ SimpleMesh_make_quad2 () 3, 2, 0, 0, 1, 3, /* Back of quad 1 */ }; - float uvs[8] = { - 0.0, 1.0, - 1.0, 1.0, - 0.0, 0.0, - 1.0, 0.0, + int uvs[8] = { + 0, 1, + 1, 1, + 0, 0, + 1, 0, }; SimpleMesh mesh; @@ -100,15 +102,14 @@ SimpleMesh_make_quad2 () glGenBuffers (1, &mesh.ebo); glBindBuffer (GL_ARRAY_BUFFER, mesh.pbo); - glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 12, positions, GL_STATIC_DRAW); + glBufferData (GL_ARRAY_BUFFER, sizeof (int) * 12, positions, GL_STATIC_DRAW); glEnableVertexAttribArray (0); - glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (float) * 3, 0); + glVertexAttribPointer (0, 3, GL_INT, GL_FALSE, sizeof (int) * 3, 0); glBindBuffer (GL_ARRAY_BUFFER, mesh.uvbo); - glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 8, uvs, GL_STATIC_DRAW); + glBufferData (GL_ARRAY_BUFFER, sizeof (int) * 8, uvs, GL_STATIC_DRAW); glEnableVertexAttribArray (1); - glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, sizeof (float) * 2, 0); - + glVertexAttribPointer (1, 2, GL_INT, GL_FALSE, sizeof (int) * 2, 0); glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh.ebo); glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * mesh.indices_len, indices, GL_STATIC_DRAW); @@ -120,16 +121,16 @@ SimpleMesh SimpleMesh_make_quad_x () { /* The positions are trivial. */ - float positions[24] = { - -1.0, -1.0, 0.0, - +1.0, -1.0, 0.0, - -1.0, 1.0, 0.0, - +1.0, 1.0, 0.0, + int positions[24] = { + -1, -1, 0, + +1, -1, 0, + -1, 1, 0, + +1, 1, 0, - 0.0, -1.0, -1.0, - 0.0, -1.0, 1.0, - 0.0, 1.0, -1.0, - 0.0, 1.0, 1.0 + 0, -1, -1, + 0, -1, 1, + 0, 1, -1, + 0, 1, 1 }; unsigned int indices[24] = { @@ -139,16 +140,16 @@ SimpleMesh_make_quad_x () 7, 6, 4, 4, 5, 7 /* Back of quad 2 */ }; - float uvs[16] = { - 0.0, 1.0, - 1.0, 1.0, - 0.0, 0.0, - 1.0, 0.0, + int uvs[16] = { + 0, 1, + 1, 1, + 0, 0, + 1, 0, - 0.0, 1.0, - 1.0, 1.0, - 0.0, 0.0, - 1.0, 0.0 + 0, 1, + 1, 1, + 0, 0, + 1, 0 }; SimpleMesh mesh; @@ -158,77 +159,17 @@ SimpleMesh_make_quad_x () glGenBuffers (1, &mesh.ebo); glBindBuffer (GL_ARRAY_BUFFER, mesh.pbo); - glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 24, positions, GL_STATIC_DRAW); + glBufferData (GL_ARRAY_BUFFER, sizeof (int) * 24, positions, GL_STATIC_DRAW); glEnableVertexAttribArray (0); - glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (float) * 3, 0); + glVertexAttribPointer (0, 3, GL_INT, GL_FALSE, sizeof (int) * 3, 0); glBindBuffer (GL_ARRAY_BUFFER, mesh.uvbo); - glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 16, uvs, GL_STATIC_DRAW); + glBufferData (GL_ARRAY_BUFFER, sizeof (int) * 16, uvs, GL_STATIC_DRAW); glEnableVertexAttribArray (1); - glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, sizeof (float) * 2, 0); + glVertexAttribPointer (1, 2, GL_INT, GL_FALSE, sizeof (int) * 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; } - -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 - }; - - /* TODO: make correct UVs. */ - - 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 c52596f..ca5802a 100644 --- a/game/src/gl/mesh.h +++ b/game/src/gl/mesh.h @@ -19,4 +19,3 @@ void SimpleMesh_render (SimpleMesh *mesh, bool wireframe); SimpleMesh SimpleMesh_make_quad1 (); SimpleMesh SimpleMesh_make_quad2 (); SimpleMesh SimpleMesh_make_quad_x (); -SimpleMesh SimpleMesh_make_cube (); diff --git a/game/src/graphics.c b/game/src/graphics.c index 97b72b7..ff84fda 100644 --- a/game/src/graphics.c +++ b/game/src/graphics.c @@ -4,8 +4,14 @@ extern vec3 camera_position; extern int last_time; SDL_Window *sdl_window; +int render_distance = 1; + static SDL_GLContext gl_context; +static uint64_t last_check_perf = 0; +static int avg_counter = 0; +static double avg_elapsed = 0; + #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 @@ -61,6 +67,9 @@ graphics_render () { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + uint64_t start = SDL_GetPerformanceCounter (); + uint64_t freq = SDL_GetPerformanceFrequency (); + mat4 projection, view; camera_get_projection (WINDOW_WIDTH / WINDOW_HEIGHT, projection); camera_get_view (view); @@ -87,6 +96,30 @@ graphics_render () glDisable (GL_BLEND); SDL_GL_SwapWindow (sdl_window); + + uint64_t now = SDL_GetPerformanceCounter(); + double elapsed_us = (double) (now - start) * 1000000.0 / (double) freq; + + avg_elapsed += elapsed_us; + avg_counter++; + + if ((now - last_check_perf) >= freq * RENDER_AVG_FREQ_S) + { + double avg = avg_elapsed / avg_counter; + + if (avg < RENDER_FRAME_BUDGET_US && render_distance < RENDER_DISTANCE_MAX) + { + render_distance++; + } + else if (avg > RENDER_FRAME_BUDGET_US && render_distance > RENDER_DISTANCE_MIN) + { + render_distance--; + } + + avg_elapsed = 0; + avg_counter = 0; + last_check_perf = now; + } } void diff --git a/game/src/graphics.h b/game/src/graphics.h index 565f0a6..e5805f9 100644 --- a/game/src/graphics.h +++ b/game/src/graphics.h @@ -13,6 +13,14 @@ #define FRUSTUM_CULL 1 +#define CHUNK_FRAME_BUDGET_US 5000 +#define ENTITY_FRAME_BUDGET_US 5000 + +#define RENDER_FRAME_BUDGET_US 16666 /* 60 FPS */ +#define RENDER_AVG_FREQ_S 10 +#define RENDER_DISTANCE_MIN 1 +#define RENDER_DISTANCE_MAX 12 + void graphics_init (); void graphics_render (); void graphics_free ();