Tengo un mundo basado en cubos como Minecraft y me pregunto si hay una manera de construir un cubo con menos de 24 vértices para poder reducir el uso de memoria.
No me parece posible por 2 razones: las normales no saldrían bien y las texturas per-face no funcionarían.
¿Es este el caso o estoy equivocado? ¿Quizás haya alguna nueva tecnología elegante de DX11 que pueda ayudar?
Editar: solo para aclarar, tengo 2 requisitos: necesito normales de superficie para cada cara de cubo para hacer una iluminación adecuada y necesito una forma de abordar un índice diferente en una matriz de textura para cada cara de cubo
Respuestas:
Si solo necesita normales por cara, y si sus texcoords para una cara son estrictamente 0/0, 0/1, 1/0, 1/1 (o similar para adaptarse a su diseño), entonces puede construir un cubo con 8 verts y 30 (tira con reinicio) o 36 (lista) índices. Obtenga las normales y los códigos de texto utilizando una búsqueda de matriz constante basada en SV_VertexID en su sombreador de vértices.
Hacer esto significa que ni siquiera necesita incluir texcoords o normales en su búfer de vértices, lo que le dará aún más ahorro de memoria.
Yendo más lejos, aún podría llegar a 24 verts por cubo, pero también usar instancing. Cada cubo tendría un tamaño fijo en su búfer de vértices (1x1x1) y tendría un factor de escala y una posición (suponiendo que sus cubos no giren, una matriz si lo hacen) como datos por instancia. En el caso no rotativo, tiene un costo único de 24 verts, pero luego cada cubo solo necesita 6 flotadores para especificar por completo. En el caso de rotación, está viendo 16 flotadores, pero incluso eso es un ahorro sustancial (es más probable que se produzca un cuello de botella en las transformaciones de la matriz en este caso, para el caso no giratorio que construye una matriz sobre la marcha) su sombreador de vértices, incluso si está hecho por vértice, es tan estúpidamente rápido que ni siquiera necesita preocuparse por eso).
Para texturas por cara, solo use una matriz de texturas. Debe asegurarse de que cada una de esas texturas en la matriz sea del mismo tamaño, por supuesto, y aún tendrá que dividir su lote actual si la matriz en sí misma necesita cambiar, pero de lo contrario hará el trabajo bien. Agregue un tercer texcoord a su definición de vértice que define el segmento de matriz que se utilizará para cada cara.
No necesita un GS con esto, y debe ejecutarse más rápido que usar uno, ya que tener habilitada la etapa de sombreado de geometría impondrá una sobrecarga adicional.
Tengo un código de referencia en mi motor que solo dibuja un montón de cubos usando este método, y puedo masticar fácilmente más de 300,000 cubos sin dejar de limpiar 60 fps, en una GPU relativamente baja, y sin hacer nada más para optimizar el proceso . Es cierto que no los estoy iluminando ni texturizando, pero tengo habilitada la mezcla alfa, desactivado el descarte de la cara posterior y, en general, se equilibra con mi parte de "no hacer nada más para optimizar", por lo que debería darle una idea razonable del tipo de estadio puede golpear con este método.
fuente
Creo que la optimización principal que puede hacer se basa en el hecho de que no todos los cubos necesitarán los 24 vértices . De hecho, los únicos cubos que necesitan 24 vértices son los que están flotando en el aire, lo que probablemente es una ocurrencia rara.
En general, solo genere quads para las caras que están en contacto con el aire . Esto significa que si dos cubos se tocan, no necesita generar vértices para la cara donde se tocan.
La imagen a continuación muestra este concepto, pero en 2D para una comprensión más fácil. En la imagen hay 11 bloques ocupados (representados por los círculos grises rellenos), que normalmente requerirían 4 x 11 = 44 bordes para representar (4 porque es un cuadrado, no un cubo). Pero como puede ver, solo necesita dibujar los bordes cuando están en contacto con un cuadrado vacío, que en este caso, solo tiene 8 bordes.
Si un ejemplo tan simple en 2D logró reducir 44 bordes a 8 bordes, imagine las ganancias en un gran mundo 3D ...
Este es el enfoque descrito en este artículo , que le recomiendo que lea, a pesar de estar dirigido a OpenGL. Sin embargo, los conceptos deberían ser bastante universales.
Probablemente también podría usar un sombreador de geometría para generar los vértices sobre la marcha en la GPU, eliminando la necesidad de almacenarlos en la memoria, pero no tengo experiencia con eso, ni sé qué tan bien funcionaría para un gran mundo.
fuente