Dynamic render distance

This commit is contained in:
2025-06-07 20:25:01 +02:00
parent ee65434e5f
commit 56b08e59f7
11 changed files with 139 additions and 154 deletions
+3
View File
@@ -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;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.
+26 -29
View File
@@ -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++;
}
}
}
-3
View File
@@ -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);
+14 -5
View File
@@ -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;
}
-2
View File
@@ -17,8 +17,6 @@
#define ENTADD(entity) (entman_add_entity (entity))
#define ENTITY_FRAME_BUDGET_US 100
typedef struct SpawnRequest
{
char *template_name;
+55 -114
View File
@@ -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;
}
-1
View File
@@ -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 ();
+33
View File
@@ -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
+8
View File
@@ -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 ();