¿Cómo obtener los bloques vistos por el jugador?

15

Estoy escribiendo un juego similar a Minecraft usando el motor Ogre y tengo un problema. Debo optimizar mi juego, porque cuando intento dibujar 10000 bloques, tengo 2 FPS ... Entonces, se me ocurrió la idea de que los bloques se visualicen en el plano y que oculten los bloques invisibles. Pero tengo un problema: ¿cómo sé qué bloques a la vez son visibles para el jugador?

Y, si conoce otros métodos de optimización para dicho juego, escriba qué y cómo usarlos en Ogre.

m4tx
fuente

Respuestas:

16

Bueno, Ogre ya implementa el sacrificio de frustum (que básicamente no dibuja nada que no se pueda ver desde la cámara), pero creo que su problema es diferente.

Realmente no deberías mostrar 10000 bloques, lo que comúnmente se hace (o al menos, en los pocos minecraft basados ​​en Ogre3d como los clones que he visto (de los cuales también estoy haciendo uno), y en el original) es crear una malla ( de alguna región NxNxN de trozos) que tiene las caras externas de los cubos mostrados. Es decir, cuando coloca 2 cubos uno al lado del otro, no se pueden ver las dos caras que se tocan y, por lo tanto, no es necesario dibujarlas.

Estas caras También deberían extraerse en algo como esto: http://www.ogre3d.org/tikiwiki/tiki-index.php?page=DynamicGrowingBuffers como tarjetas de vídeo modernas prefieren una malla de polígonos 100000 1000 frente a 100 mallas de polígonos.

Elva
fuente
10

Hay un par de aspectos de este problema. En primer lugar, ¿cómo estás dibujando tus 10000 bloques? ¿Realmente los estás dibujando como 10000 objeto separado? Si es así, esto es casi seguro su cuello de botella, no la falta de eliminación de oclusión. Debería agrupar estos bloques en un número menor de mallas (quizás unos pocos miles por malla) para reducir las llamadas de extracción.

En cuanto a su pregunta real, hay tres tipos de eliminación de oclusiones que me vienen a la mente.

1) Bloques fuera de la vista frustum. Esto significa bloques que están detrás de ti o dos a un lado. Ogre ya los elimina a través del sacrificio de vista frustum.

2) Bloques que están 'subterráneos' o completamente rodeados por otros bloques para que nunca se puedan ver desde ningún ángulo. Puede identificarlos mirando los bloques vecinos siz. Si todos son sólidos, su bloque está oculto. La GPU nunca debería escuchar acerca de estos bloques; deben omitirse cuando está construyendo la malla que representa su superficie.

3) Bloques que están en la superficie y se pueden ver desde algunas posiciones en el nivel, pero que actualmente están ocultos por una colina (o algo así). Este es el caso más complicado que no he abordado, pero hay una buena posibilidad de que las consultas de oclusión de hardware se puedan utilizar para este caso.

Es un complemento descarado, pero tengo una biblioteca bastante madura que varias personas usan para desarrollar clones de Minecraft, incluidos algunos que usan Ogre. Usted define el contenido del volumen y genera la malla de superficie que luego puede renderizar. Aquí está la página de inicio:

http://www.thermite3d.org/

Y aquí hay un video del proyecto de otra persona que lo está usando:

http://www.youtube.com/watch?v=Jju6WRPEK7o

David Williams
fuente
4

Puede utilizar la selección de la cara posterior para eliminar los vértices y sus píxeles asociados que no se enfrentan al jugador. La amortiguación de profundidad debería ocuparse del resto. 10k bloques realmente no es mucho, mi 5770 puede renderizar 100k verts a 1500fps. Creo que estás haciendo algo muy mal.

DeadMG
fuente
Estoy de acuerdo. Este es probablemente un problema con cualquier otra cosa.
Notabene
1

Si tiene 10000 objetos separados, el cuello de botella es probablemente un recuento primitivo, no vértice, polígono o relleno. Hornee sus objetos en un número menor de objetos poligonales más altos para mayor velocidad.

Minecraft tiene un concepto de bloques de cubos, pero no puedo encontrar la referencia en este momento.

Aquí también están mis experimentos para dibujar toneladas de cubos con varias técnicas. No incluye hornear (todavía).

Jari Komppa
fuente
0

Lo que hago es después de crear mi conjunto de bloques, pero antes de crear los vértices, ejecuto un sub llamado UpdateBlockVisiblility.

El submarino simplemente verifica los vecinos del bloque y actualiza los bloques booleanos visibles en consecuencia.

#define BLOCKFACE_NORTH 0

#define BLOCKFACE_SOUTH 1 

etc etc etc

if(IsBlockAt(NorthOfBlock))
  Blocks[Whatever].facevisible[BLOCKFACE_NORTH] = false;

¡Entonces solo creo los vértices para la cara si es visible! Sencillo :)

BMW
fuente