[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. */
 | 
					  /* Draw History. */
 | 
				
			||||||
  for(size_t i = _scroll_offset; i < _history.size(); ++i) {
 | 
					  for(size_t i = _scroll_offset; i < _history.size(); ++i) {
 | 
				
			||||||
    float line_y_pos = y_screen + padding + ((i - _scroll_offset) * line_height);
 | 
					    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);
 | 
					    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();
 | 
					  context.ui_renderer->flush_text();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Pass 2: Windows Render in order, last window is top-most. */
 | 
					  /* Pass 2: Windows Render in order, last window is top-most. */
 | 
				
			||||||
  for(const auto& win : _windows) {
 | 
					  for(size_t i = 0; i < _windows.size(); ++i) {
 | 
				
			||||||
    if(!win->is_minimized()) {
 | 
					    auto& win_i = _windows[i];
 | 
				
			||||||
      win.get()->render(context);
 | 
					    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;
 | 
					  float current_y = y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for(size_t i = _scroll_offset; i < _buffer->get_line_count(); ++i) {
 | 
					  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);
 | 
					    std::string line = _buffer->get_line(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(show_cursor && (int)i == cursor_pos.row) {
 | 
					    if(show_cursor && (int)i == cursor_pos.row) {
 | 
				
			||||||
 | 
				
			|||||||
@ -43,6 +43,10 @@ const std::string& UIWindow::get_title(void) const {
 | 
				
			|||||||
  return _title;
 | 
					  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 {
 | 
					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 &&
 | 
					  return (mouse_x >= _x + _width  - _resize_margin && mouse_x <= _x + _width &&
 | 
				
			||||||
          mouse_y >= _y + _height - _resize_margin &&
 | 
					          mouse_y >= _y + _height - _resize_margin &&
 | 
				
			||||||
 | 
				
			|||||||
@ -43,6 +43,7 @@ public:
 | 
				
			|||||||
  IWindowContent* get_content(void);
 | 
					  IWindowContent* get_content(void);
 | 
				
			||||||
  bool is_mouse_over_resize_handle(int mouse_x, int mouse_y) const;
 | 
					  bool is_mouse_over_resize_handle(int mouse_x, int mouse_y) const;
 | 
				
			||||||
  const std::string& get_title(void) const;
 | 
					  const std::string& get_title(void) const;
 | 
				
			||||||
 | 
					  Rect get_rect(void) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  friend class Taskbar; /* Allow taskbar to access private members. */
 | 
					  friend class Taskbar; /* Allow taskbar to access private members. */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user