static void make_vertices(Object *object, MapBlock *block, bool hide_edges)
{
- v3s32 node_bp = {block->pos.x * MAPBLOCK_SIZE, block->pos.y * MAPBLOCK_SIZE, block->pos.z * MAPBLOCK_SIZE};
+ object->visible = false;
+ v3s32 node_bp = {
+ block->pos.x * MAPBLOCK_SIZE,
+ block->pos.y * MAPBLOCK_SIZE,
+ block->pos.z * MAPBLOCK_SIZE
+ };
ITERATE_MAPBLOCK {
MapNode *node = &block->data[x][y][z];
ClientNodeDefintion *def = &client_node_definitions[node->type];
if (def->visibility != NV_NONE) {
- v3f32 offset = {x - half_block_size - 0.5, y - half_block_size - 0.5, z - half_block_size - 0.5};
+ v3f32 offset = {
+ x - half_block_size - 0.5,
+ y - half_block_size - 0.5,
+ z - half_block_size - 0.5
+ };
for (int f = 0; f < 6; f++) {
v3s8 npos = {
z + fdir[f].z,
};
- Node neighbor;
+ bool direct_neighbor = npos.x >= 0 && npos.x < MAPBLOCK_SIZE
+ && npos.y >= 0 && npos.y < MAPBLOCK_SIZE
+ && npos.z >= 0 && npos.z < MAPBLOCK_SIZE;
- if (npos.x >= 0 && npos.x < MAPBLOCK_SIZE && npos.y >= 0 && npos.y < MAPBLOCK_SIZE && npos.z >= 0 && npos.z < MAPBLOCK_SIZE)
- neighbor = block->data[npos.x][npos.y][npos.z].type;
- else if (hide_edges) {
- MapNode nn = map_get_node(client_map.map, (v3s32) {npos.x + node_bp.x, npos.y + node_bp.y, npos.z + node_bp.z});
- neighbor = nn.type;
- } else {
- neighbor = NODE_AIR;
- }
+ MapNode neighbor = direct_neighbor
+ ? block->data[npos.x][npos.y][npos.z]
+ : map_get_node(client_map.map, (v3s32) {npos.x + node_bp.x, npos.y + node_bp.y, npos.z + node_bp.z});
+
+ bool transparency_edge = def->visibility != NV_TRANSPARENT || neighbor.type != node->type;
+
+ bool render_node = neighbor.type != NODE_UNLOADED
+ && client_node_definitions[neighbor.type].visibility != NV_SOLID
+ && transparency_edge;
+
+ object->visible = object->visible || render_node;
+
+ if (! hide_edges && ! direct_neighbor)
+ render_node = transparency_edge;
- if (neighbor != NODE_UNLOADED && client_node_definitions[neighbor].visibility != NV_SOLID && (def->visibility != NV_TRANSPARENT || neighbor != node->type)) {
+ if (render_node) {
+ object->transparent = object->transparent || def->visibility == NV_TRANSPARENT;
object_set_texture(object, def->tiles.textures[f]);
for (int v = 0; v < 6; v++) {
#include "client/client_map.h"
#include "client/client_player.h"
#include "util.h"
-#define MAX_BLOCK_REQUESTS 4
+#define MAX_BLOCK_REQUESTS 8
struct ClientMap client_map;
Client *client;
glFrontFace(GL_CCW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- scene_render(dtime);
-
- glDisable(GL_CULL_FACE);
sky_render();
-
- glDisable(GL_DEPTH_TEST);
+ scene_render(dtime);
gui_render();
}
void gui_render()
{
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
bintree_traverse(&gui_root.children, BTT_INORDER, &render_element, NULL);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
}
GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def)
obj->meshes_count = 0;
obj->visible = true;
obj->wireframe = false;
- obj->box = (aabb3f32) {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}};
obj->frustum_culling = false;
+ obj->transparent = false;
+ obj->box = (aabb3f32) {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}};
obj->current_face = NULL;
obj->faces = array_create(sizeof(ObjectFace));
obj->on_render = NULL;
#pragma GCC diagnostic pop
}
-void object_render(Object *obj, f64 dtime)
+bool object_before_render(Object *obj, f64 dtime)
{
if (obj->on_render)
obj->on_render(obj, dtime);
if (! obj->visible)
- return;
+ return false;
if (obj->frustum_culling) {
aabb3f32 box = {v3f32_add(obj->box.min, obj->pos), v3f32_add(obj->box.max, obj->pos), };
if (! frustum_is_visible(box))
- return;
+ return false;
}
+ return true;
+}
+
+void object_render(Object *obj)
+{
glUniformMatrix4fv(scene.loc_model, 1, GL_FALSE, obj->transform[0]);
if (obj->wireframe)
bool visible;
bool wireframe;
bool frustum_culling;
+ bool transparent;
aabb3f32 box;
ObjectFace *current_face;
Array faces;
void object_add_vertex(Object *obj, Vertex3D *vertex);
bool object_add_to_scene(Object *obj);
void object_transform(Object *obj);
-void object_render(Object *obj, f64 dtime);
+bool object_before_render(Object *obj, f64 dtime);
+void object_render(Object *obj);
#endif
struct Scene scene;
+static int bintree_compare_f32(void *v1, void *v2, unused Bintree *tree)
+{
+ f32 diff = (*(f32 *) v2) - (*(f32 *) v1);
+ return CMPBOUNDS(diff);
+}
+
bool scene_init()
{
- scene.objects = list_create(NULL),
+ scene.objects = list_create(NULL);
+ scene.render_objects = bintree_create(sizeof(f32), &bintree_compare_f32);
pthread_mutex_init(&scene.mtx, NULL);
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &scene.max_texture_units);
glProgramUniform1iv(scene.prog, glGetUniformLocation(scene.prog, "textures"), scene.max_texture_units, texture_indices);
scene.fov = 86.1f;
- scene.render_distance = 255.0f + 32.0f;
+ scene.render_distance = 255.0f;
return true;
}
pthread_mutex_unlock(&scene.mtx);
}
+static void bintree_render_object(BintreeNode *node, unused void *arg)
+{
+ object_render(node->value);
+}
+
void scene_render(f64 dtime)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
mat4x4_mul(scene.VP, scene.projection, camera.view);
+#pragma GCC diagnostic pop
vec4 base_sunlight_dir = {0.0f, 0.0f, -1.0f, 1.0f};
vec4 sunlight_dir;
mat4x4 sunlight_mat;
mat4x4_identity(sunlight_mat);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
mat4x4_rotate(sunlight_mat, sunlight_mat, 1.0f, 0.0f, 0.0f, get_sun_angle() + M_PI / 2.0f);
mat4x4_mul_vec4(sunlight_dir, sunlight_mat, base_sunlight_dir);
#pragma GCC diagnostic pop
free(pair);
object_delete(obj);
} else {
- object_render(obj, dtime);
+ 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));
+ if (distance < scene.render_distance && object_before_render(obj, dtime)) {
+ if (obj->transparent)
+ bintree_insert(&scene.render_objects, &distance, obj);
+ else
+ object_render(obj);
+ }
pairptr = &pair->next;
}
}
+
+ bintree_traverse(&scene.render_objects, BTT_INORDER, &bintree_render_object, NULL);
+ bintree_clear(&scene.render_objects, NULL, NULL);
}
void scene_on_resize(int width, int height)
{
- mat4x4_perspective(scene.projection, scene.fov / 180.0f * M_PI, (float) width / (float) height, 0.01f, scene.render_distance);
+ mat4x4_perspective(scene.projection, scene.fov / 180.0f * M_PI, (float) width / (float) height, 0.01f, scene.render_distance + 28.0f);
}
GLuint scene_get_max_texture_units()
#include <stdbool.h>
#include <pthread.h>
#include <linmath.h/linmath.h>
+#include <dragontype/bintree.h>
#include <dragontype/list.h>
#include <dragontype/number.h>
#include "client/object.h"
extern struct Scene
{
List objects;
+ Bintree render_objects;
pthread_mutex_t mtx;
GLuint prog;
GLint loc_model;
mat4x4 MVP;
mat4x4_mul(MVP, VP, model);
+ glDisable(GL_CULL_FACE);
glDepthFunc(GL_LEQUAL);
glUseProgram(sky.skybox_prog);
mesh_render(sky.clouds_mesh);
glDepthFunc(GL_LESS);
+ glEnable(GL_CULL_FACE);
}
#pragma GCC diagnostic pop