[Add] Occlusion culling.
Prevents rendering of UI windows that are completely hidden by other windows. Desktop rendering now checks if a window is fully occluded by any single window higher in the Z-order. If a window is determined to be hidden, its entire render function can be skipped. This is a pragmatic implementation that handles the most common occlusion scenario (i.e., a maximised window). There would be little benefit of other edge cases in the particular game I think.
This commit is contained in:
parent
b1392c2e6b
commit
d992cb54bf
@ -125,6 +125,8 @@ void Terminal::render(const RenderContext& context, int x, int y_screen, int y_g
|
||||
/* Draw History. */
|
||||
for(size_t i = _scroll_offset; i < _history.size(); ++i) {
|
||||
float line_y_pos = y_screen + padding + ((i - _scroll_offset) * line_height);
|
||||
/* Culling: If line is already below the view, stop. */
|
||||
if(line_y_pos > y_screen + height) { break; }
|
||||
context.ui_renderer->render_text(_history[i].c_str(), x+padding, line_y_pos+18, white);
|
||||
}
|
||||
|
||||
|
||||
@ -214,9 +214,27 @@ void Desktop::render(const RenderContext& context) {
|
||||
context.ui_renderer->flush_text();
|
||||
|
||||
/* Pass 2: Windows Render in order, last window is top-most. */
|
||||
for(const auto& win : _windows) {
|
||||
if(!win->is_minimized()) {
|
||||
win.get()->render(context);
|
||||
for(size_t i = 0; i < _windows.size(); ++i) {
|
||||
auto& win_i = _windows[i];
|
||||
if(win_i->is_minimized()) continue;
|
||||
|
||||
bool is_occluded = false;
|
||||
Rect rect_i = win_i->get_rect();
|
||||
|
||||
/* Check against all windows on top of this one. */
|
||||
for(size_t j = i+1; j < _windows.size(); ++j) {
|
||||
auto& win_j = _windows[j];
|
||||
if(win_j->is_minimized()) continue;
|
||||
|
||||
Rect rect_j = win_j->get_rect();
|
||||
if(rect_i.x >= rect_j.x && (rect_i.x + rect_i.w) <= (rect_j.x + rect_j.w) &&
|
||||
rect_i.y >= rect_j.y && (rect_i.y + rect_i.h) <= (rect_j.y + rect_j.h)) {
|
||||
is_occluded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!is_occluded) {
|
||||
win_i->render(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +82,14 @@ void TextView::render(UIRenderer* ui_renderer, int x, int y, int width, int heig
|
||||
float current_y = y;
|
||||
|
||||
for(size_t i = _scroll_offset; i < _buffer->get_line_count(); ++i) {
|
||||
/*
|
||||
* Culling: If the top of the current line is already below the bottom of the
|
||||
* view, we can stop rendering completely.
|
||||
*/
|
||||
if(current_y > y + height) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::string line = _buffer->get_line(i);
|
||||
|
||||
if(show_cursor && (int)i == cursor_pos.row) {
|
||||
|
||||
@ -43,6 +43,10 @@ const std::string& UIWindow::get_title(void) const {
|
||||
return _title;
|
||||
}
|
||||
|
||||
Rect UIWindow::get_rect(void) const {
|
||||
return { _x, _y, _width, _height };
|
||||
}
|
||||
|
||||
bool UIWindow::is_mouse_over_resize_handle(int mouse_x, int mouse_y) const {
|
||||
return (mouse_x >= _x + _width - _resize_margin && mouse_x <= _x + _width &&
|
||||
mouse_y >= _y + _height - _resize_margin &&
|
||||
|
||||
@ -43,6 +43,7 @@ public:
|
||||
IWindowContent* get_content(void);
|
||||
bool is_mouse_over_resize_handle(int mouse_x, int mouse_y) const;
|
||||
const std::string& get_title(void) const;
|
||||
Rect get_rect(void) const;
|
||||
|
||||
private:
|
||||
friend class Taskbar; /* Allow taskbar to access private members. */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user