[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