OO arquitectura para renderizar en juegos basados en sombreadores

Sigo golpeando este problema cuando construyo motores de juego donde mis clases quieren verse así:

interface Entity {
  draw();
}

class World {
  draw() {
    for (e in entities)
      e.draw();
  }
}

Eso es solo un pseudocódigo para mostrar aproximadamente cómo ocurre el dibujo. Cada subclase de entidad implementa su propio dibujo. El mundo recorre todas las entidades sin ningún orden en particular y les dice que se dibujen una por una.

Pero con gráficos basados en sombreadores, esto tiende a ser terriblemente ineficiente o incluso inviable. Cada tipo de entidad probablemente tendrá su propio programa de sombreador. Para minimizar los cambios en el programa, todas las entidades de cada tipo en particular deben dibujarsejunto. Los tipos simples de entidades, como las partículas, también pueden querer agregar su dibujo de otras maneras, como compartir una gran matriz de vértices. Y se vuelve muy complicado con la combinación y tal, donde algunos tipos de entidades deben representarse en ciertos momentos en relación con otros, o incluso en múltiples momentos para diferentes pases.

Con lo que normalmente termino es una especie de renderizador singleton para cada clase de entidad que mantiene una lista de todas las instancias y las dibuja todas a la vez. Eso no es tan malo ya que separa el dibujo de la lógica del juego. Pero el procesador necesita descubrir qué subconjunto de entidades dibujar y necesita acceso a múltiples partes diferentes de la tubería de gráficos. Aquí es donde mi modelo de objetos tiende a desordenarse, con muchos códigos duplicados, acoplamiento estrecho y otras cosas malas.

Así que mi pregunta es: ¿cuál es una buena arquitectura para este tipo de dibujo de juegos que sea eficiente, versátil y modular?

Respuestas a la pregunta(2)

Su respuesta a la pregunta