3 #include "client/camera.h"
4 #include "client/client.h"
5 #include "client/frustum.h"
6 #include "client/scene.h"
7 #include "client/shader.h"
13 static int bintree_compare_f32(void *v1, void *v2, unused Bintree *tree)
15 f32 diff = (*(f32 *) v2) - (*(f32 *) v1);
16 return CMPBOUNDS(diff);
21 scene.objects = list_create(NULL);
22 scene.transparent_objects = bintree_create(sizeof(f32), &bintree_compare_f32);
23 pthread_mutex_init(&scene.mtx, NULL);
25 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &scene.max_texture_units);
27 char max_texture_units_def[BUFSIZ];
28 sprintf(max_texture_units_def, "#define MAX_TEXTURE_UNITS %d\n", scene.max_texture_units);
30 if (! shader_program_create(RESSOURCEPATH "shaders/3d", &scene.prog, max_texture_units_def)) {
31 fprintf(stderr, "Failed to create 3D shader program\n");
35 scene.loc_model = glGetUniformLocation(scene.prog, "model");
36 scene.loc_VP = glGetUniformLocation(scene.prog, "VP");
37 scene.loc_daylight = glGetUniformLocation(scene.prog, "daylight");
38 scene.loc_lightDir = glGetUniformLocation(scene.prog, "lightDir");
39 scene.loc_cameraPos = glGetUniformLocation(scene.prog, "cameraPos");
41 GLint texture_indices[scene.max_texture_units];
42 for (GLint i = 0; i < scene.max_texture_units; i++)
43 texture_indices[i] = i;
45 glProgramUniform1iv(scene.prog, glGetUniformLocation(scene.prog, "textures"), scene.max_texture_units, texture_indices);
48 scene.render_distance = 255.0f;
53 static void list_delete_object(void *key, unused void *value, unused void *arg)
60 list_clear_func(&scene.objects, &list_delete_object, NULL);
61 pthread_mutex_destroy(&scene.mtx);
62 glDeleteProgram(scene.prog);
65 void scene_add_object(Object *obj)
67 pthread_mutex_lock(&scene.mtx);
68 list_put(&scene.objects, obj, NULL);
69 pthread_mutex_unlock(&scene.mtx);
72 static void bintree_render_object(BintreeNode *node, unused void *arg)
74 object_render(node->value);
77 void scene_render(f64 dtime)
79 #pragma GCC diagnostic push
80 #pragma GCC diagnostic ignored "-Wpedantic"
81 mat4x4_mul(scene.VP, scene.projection, camera.view);
82 #pragma GCC diagnostic pop
84 vec4 base_sunlight_dir = {0.0f, 0.0f, -1.0f, 1.0f};
87 mat4x4_identity(sunlight_mat);
89 #pragma GCC diagnostic push
90 #pragma GCC diagnostic ignored "-Wpedantic"
91 mat4x4_rotate(sunlight_mat, sunlight_mat, 1.0f, 0.0f, 0.0f, get_sun_angle() + M_PI / 2.0f);
92 mat4x4_mul_vec4(sunlight_dir, sunlight_mat, base_sunlight_dir);
93 #pragma GCC diagnostic pop
95 frustum_update(scene.VP);
97 glUseProgram(scene.prog);
98 glUniformMatrix4fv(scene.loc_VP, 1, GL_FALSE, scene.VP[0]);
99 glUniform3f(scene.loc_lightDir, sunlight_dir[0], sunlight_dir[1], sunlight_dir[2]);
100 glUniform3f(scene.loc_cameraPos, camera.eye[0], camera.eye[1], camera.eye[2]);
101 glUniform1f(scene.loc_daylight, get_daylight());
103 for (ListPair **pairptr = &scene.objects.first; *pairptr != NULL; ) {
104 ListPair *pair = *pairptr;
105 Object *obj = pair->key;
107 pthread_mutex_lock(&scene.mtx);
108 *pairptr = pair->next;
109 pthread_mutex_unlock(&scene.mtx);
113 f32 distance = sqrt(pow(obj->pos.x - camera.eye[0], 2) + pow(obj->pos.y - camera.eye[1], 2) + pow(obj->pos.z - camera.eye[2], 2));
114 if (distance < scene.render_distance && object_before_render(obj, dtime)) {
115 if (obj->transparent)
116 bintree_insert(&scene.transparent_objects, &distance, obj);
120 pairptr = &pair->next;
124 bintree_traverse(&scene.transparent_objects, BTT_INORDER, &bintree_render_object, NULL);
125 bintree_clear(&scene.transparent_objects, NULL, NULL);
128 void scene_on_resize(int width, int height)
130 mat4x4_perspective(scene.projection, scene.fov / 180.0f * M_PI, (float) width / (float) height, 0.01f, scene.render_distance + 28.0f);
133 GLuint scene_get_max_texture_units()
135 return scene.max_texture_units;