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

Fix viewport sorting being wrong on parent/child relation

This commit is contained in:
MinusKube
2022-07-17 01:59:13 +02:00
parent 3953c1aa73
commit be09a87ff9
2 changed files with 49 additions and 18 deletions

View File

@@ -72,6 +72,41 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
return xf;
}
Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() {
// We need to sort the viewports in a "topological order",
// children first and parents last, we use the Kahn's algorithm to achieve that.
Vector<Viewport *> result;
List<Viewport *> nodes;
for (Viewport *viewport : active_viewports) {
if (viewport->parent.is_valid()) {
continue;
}
nodes.push_back(viewport);
}
while (!nodes.is_empty()) {
Viewport *node = nodes[0];
nodes.pop_front();
result.insert(0, node);
for (Viewport *child : active_viewports) {
if (child->parent != node->self) {
continue;
}
if (!nodes.find(child)) {
nodes.push_back(child);
}
}
}
return result;
}
void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
if (p_viewport->render_buffers.is_valid()) {
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
@@ -544,8 +579,10 @@ void RendererViewport::draw_viewports() {
set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
}
//sort viewports
active_viewports.sort_custom<ViewportSort>();
if (sorted_active_viewports_dirty) {
sorted_active_viewports = _sort_active_viewports();
sorted_active_viewports_dirty = false;
}
HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;
//draw viewports
@@ -554,9 +591,9 @@ void RendererViewport::draw_viewports() {
//determine what is visible
draw_viewports_pass++;
for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
for (int i = sorted_active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
Viewport *vp = active_viewports[i];
Viewport *vp = sorted_active_viewports[i];
if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED) {
continue;
@@ -617,8 +654,8 @@ void RendererViewport::draw_viewports() {
int objects_drawn = 0;
int draw_calls_used = 0;
for (int i = 0; i < active_viewports.size(); i++) {
Viewport *vp = active_viewports[i];
for (int i = 0; i < sorted_active_viewports.size(); i++) {
Viewport *vp = sorted_active_viewports[i];
if (vp->last_pass != draw_viewports_pass) {
continue; //should not draw
@@ -810,6 +847,8 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
} else {
active_viewports.erase(viewport);
}
sorted_active_viewports_dirty = true;
}
void RendererViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) {
@@ -1239,6 +1278,7 @@ bool RendererViewport::free(RID p_rid) {
viewport_set_scenario(p_rid, RID());
active_viewports.erase(viewport);
sorted_active_viewports_dirty = true;
if (viewport->use_occlusion_culling) {
RendererSceneOcclusionCull::get_singleton()->remove_buffer(p_rid);