1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Implement multiple occlusion polygons within each TileSet occlusion layer

This commit is contained in:
Gilles Roudière
2024-06-11 12:59:55 +02:00
parent 8120e0324a
commit d75c5ec7ba
8 changed files with 345 additions and 114 deletions

View File

@@ -443,13 +443,15 @@ void TileMapLayer::_rendering_notification(int p_what) {
Transform2D tilemap_xform = get_global_transform();
for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
const CellData &cell_data = kv.value;
for (const RID &occluder : cell_data.occluders) {
if (occluder.is_null()) {
continue;
for (const LocalVector<RID> &polygons : cell_data.occluders) {
for (const RID &rid : polygons) {
if (rid.is_null()) {
continue;
}
Transform2D xform(0, tile_set->map_to_local(kv.key));
rs->canvas_light_occluder_attach_to_canvas(rid, get_canvas());
rs->canvas_light_occluder_set_transform(rid, tilemap_xform * xform);
}
Transform2D xform(0, tile_set->map_to_local(kv.key));
rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
rs->canvas_light_occluder_set_transform(occluder, tilemap_xform * xform);
}
}
}
@@ -557,8 +559,10 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
RenderingServer *rs = RenderingServer::get_singleton();
// Free the occluders.
for (const RID &rid : r_cell_data.occluders) {
rs->free(rid);
for (const LocalVector<RID> &polygons : r_cell_data.occluders) {
for (const RID &rid : polygons) {
rs->free(rid);
}
}
r_cell_data.occluders.clear();
}
@@ -566,11 +570,12 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
RenderingServer *rs = RenderingServer::get_singleton();
// Free unused occluders then resize the occluders array.
// Free unused occluders then resize the occluder array.
for (uint32_t i = tile_set->get_occlusion_layers_count(); i < r_cell_data.occluders.size(); i++) {
RID occluder_id = r_cell_data.occluders[i];
if (occluder_id.is_valid()) {
rs->free(occluder_id);
for (const RID &occluder_id : r_cell_data.occluders[i]) {
if (occluder_id.is_valid()) {
rs->free(occluder_id);
}
}
}
r_cell_data.occluders.resize(tile_set->get_occlusion_layers_count());
@@ -598,30 +603,42 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
// Create, update or clear occluders.
bool needs_set_not_interpolated = is_inside_tree() && get_tree()->is_physics_interpolation_enabled() && !is_physics_interpolated();
for (uint32_t occlusion_layer_index = 0; occlusion_layer_index < r_cell_data.occluders.size(); occlusion_layer_index++) {
Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder(occlusion_layer_index);
LocalVector<RID> &occluders = r_cell_data.occluders[occlusion_layer_index];
RID &occluder = r_cell_data.occluders[occlusion_layer_index];
if (occluder_polygon.is_valid()) {
// Create or update occluder.
Transform2D xform;
xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
if (!occluder.is_valid()) {
occluder = rs->canvas_light_occluder_create();
if (needs_set_not_interpolated) {
rs->canvas_light_occluder_set_interpolated(occluder, false);
}
// Free unused occluders then resize the occluders array.
for (uint32_t i = tile_data->get_occluder_polygons_count(occlusion_layer_index); i < r_cell_data.occluders[occlusion_layer_index].size(); i++) {
RID occluder_id = occluders[i];
if (occluder_id.is_valid()) {
rs->free(occluder_id);
}
rs->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform);
rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder(occlusion_layer_index, flip_h, flip_v, transpose)->get_rid());
rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index));
rs->canvas_light_occluder_set_as_sdf_collision(occluder, tile_set->get_occlusion_layer_sdf_collision(occlusion_layer_index));
} else {
// Clear occluder.
if (occluder.is_valid()) {
rs->free(occluder);
occluder = RID();
}
occluders.resize(tile_data->get_occluder_polygons_count(occlusion_layer_index));
for (uint32_t occlusion_polygon_index = 0; occlusion_polygon_index < occluders.size(); occlusion_polygon_index++) {
RID &occluder = occluders[occlusion_polygon_index];
Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder_polygon(occlusion_layer_index, occlusion_polygon_index);
if (occluder_polygon.is_valid()) {
// Create or update occluder.
Transform2D xform;
xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
if (!occluder.is_valid()) {
occluder = rs->canvas_light_occluder_create();
if (needs_set_not_interpolated) {
rs->canvas_light_occluder_set_interpolated(occluder, false);
}
}
rs->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform);
rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder_polygon(occlusion_layer_index, occlusion_polygon_index, flip_h, flip_v, transpose)->get_rid());
rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index));
rs->canvas_light_occluder_set_as_sdf_collision(occluder, tile_set->get_occlusion_layer_sdf_collision(occlusion_layer_index));
} else {
// Clear occluder.
if (occluder.is_valid()) {
rs->free(occluder);
occluder = RID();
}
}
}
}
@@ -1709,11 +1726,13 @@ void TileMapLayer::_physics_interpolated_changed() {
}
for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
for (const RID &occluder : E.value.occluders) {
if (occluder.is_valid()) {
rs->canvas_light_occluder_set_interpolated(occluder, interpolated);
if (needs_reset) {
rs->canvas_light_occluder_reset_physics_interpolation(occluder);
for (const LocalVector<RID> &polygons : E.value.occluders) {
for (const RID &occluder_id : polygons) {
if (occluder_id.is_valid()) {
rs->canvas_light_occluder_set_interpolated(occluder_id, interpolated);
if (needs_reset) {
rs->canvas_light_occluder_reset_physics_interpolation(occluder_id);
}
}
}
}