2011-07-05 14 views
10

sigo golpeando este problema en la construcción de motores de juego donde mis clases quieren tener este aspecto:arquitectura OO para la prestación de los juegos basados ​​shader

interface Entity { 
    draw(); 
} 

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

eso es sólo pseudo-código que muestran qué 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 uno por uno.

Pero con gráficos basados ​​en sombreado, esto tiende a ser terriblemente ineficiente o incluso inviable. Cada tipo de entidad probablemente tendrá su propio programa de sombreado. Para minimizar los cambios de programa, todas las entidades de cada tipo particular deben dibujarse juntas . 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 pone realmente peludo con la mezcla y tal, cuando algunos tipos de entidad necesitan renderizarse en ciertos momentos en relación con otros, o incluso en múltiples ocasiones para pases diferentes.

Lo que normalmente termino con algún tipo de renderizador individual 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 averiguar qué subconjunto de entidades dibujar y necesita acceder a múltiples partes diferentes de la canalización de gráficos. Aquí es donde mi modelo de objetos tiende a desordenarse, con muchos códigos duplicados, acoplamiento cerrado y otras cosas malas.

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

+0

Es bueno comenzar con el hecho de que lo estás separando de todo lo demás, y parece que es complicado porque es ... bueno ... _messy_. ** Necesario ** lío es desafortunado, pero sigue siendo necesario. Pero dudo que veas esto como una respuesta ... –

Respuesta

1

No es una pregunta fácil de contestar, ya que hay muchas formas de resolver el problema. Una buena idea es investigar algunos motores de Juego/Rendering y ver cómo se maneja esto allí. Un buen punto de partida sería Ogre, ya que está bien documentado y es de código abierto.

Hasta donde yo sé, separa los datos de vértice de los componentes del material (sombreadores) a través de los scripts de material incorporados. El renderizador mismo sabe qué malla se va a dibujar en qué orden y con qué sombreado (y sus pases).

Sé que esta respuesta es un poco vaga, pero espero darte una pista útil.

8

Utilice un enfoque en dos etapas: Primer bucle a través de todas las entidades, pero en lugar de dibujar, que se inserten referencias en una (la) lista de lotes de dibujo. Luego, clasifique la lista por estado OpenGL y uso del sombreador; después de clasificar insertar objetos del cambiador de estado en cada transición de estado.

Finalmente, recorra la lista ejecutando la rutina de dibujo de cada objeto al que se hace referencia en la lista.

+0

¿y si tienes motores diferentes? OpenGL, DirectX? – GorillaApe

+0

@Parhs: Ni OpenGL ni DirectX son motores. Ellos son API. Y esta primera etapa llamada "configuración de fotogramas" se realiza generalmente en partes mediante el código de procesador que habla con la API y en parte con el código de administración de escena. Por ejemplo, la eliminación del frustum es algo para lo que el código de escena es más adecuado, la textura y el estado del sombreador se deben ordenar por el código del procesador. Además, no tienes que hacer todo de una vez. Está perfectamente bien atravesar primero (en el código de escena) sobre todos los cuadros de delimitación para seleccionar y clasificar por profundidad. A continuación, entregue esta lista al procesador para un mayor refinamiento. – datenwolf

+0

Gracias por responder. Sin embargo, mi problema está aquí.Dijiste "ejecutar la rutina de dibujo de cada objeto". ¿Qué sucede si quiere usar múltiples API (direct2d, opengl, etc.)? Me refiero a dibujar() dentro de cada objeto debe tener implementación para todas las API? ¿O el renderizador se ocupa de dibujar también? – GorillaApe