Crear normales de vértice compartidas en GPU

9

Principalmente he logrado portar una implementación de Marching Cubes desde la CPU a los sombreadores de cómputo OpenGL, pero aún no he abordado las normales y me pregunto cuál es la mejor manera de hacerlo.

Mi implementación se ocupa específicamente de los campos con valores binarios (estoy tratando de modelar funciones fractales 3D que aún no tienen un estimador de distancia), por lo que los métodos de gradiente y diferencias hacia adelante no funcionarán. He compartido vértices trabajando, y la implementación de mi CPU utiliza el método de Quilez descrito aquí para acumular normales de cara en cada vértice vecino.

Podría portar esta implementación a otro sombreador, pero el problema que veo con esto es la gran cantidad de átomos necesarios. Dado que solo podemos usar atómicos en tipos enteros escalares, y no puedo pensar en una forma de empacar 3 entradas firmadas en 1 de forma sumable, eso significa 3 ejes * 3 vértices = 9 adiciones atómicas por invocación de sombreador. Se extenderán por toda la memoria, por supuesto, por lo que no es como golpear un solo contador atómico 9 veces, pero aún parece mucho.

La otra alternativa es ejecutar una invocación de sombreado por polígono y construir la lista de caras normales (probablemente podría empacar en x10y10z10 de esta manera), luego un sombreador por vértice para acumular todas las normales de caras vecinas. Sin embargo, este sería un enorme problema de memoria, el espacio de almacenamiento de los índices de la cara necesitaría 12 int por vértice para lidiar con el peor de los casos. También está el problema de cómo escribir en este almacenamiento sin recurrir nuevamente a los atómicos para calcular cuántas caras ya se han escrito en un vértice particular.

¿Alguien tiene alguna idea mejor sobre cómo hacer esto?

russ
fuente

Respuestas:

5

Para una solución única de nVidia, puede utilizar intrínsecos de adición atómica de punto flotante (como NvInterlockedAddFp32) Desbloqueo de intrínsecos de GPU en HLSL | Desarrollador NVIDIA

Intenté esto en una malla de 80,000 vértices y es bastante rápido (algo así como 1 o 2 ms en una GTX980M, si no recuerdo mal)

Solo tenga cuidado de compilar sus sombreadores en la versión para que los intrínsecos funcionen (debido a la limitación / error de nvidia)

También tenga cuidado con las divisiones de vértices (debido a discontinuidades UV, por ejemplo), tendrá que manejarlas o de lo contrario tendrá bordes duros no deseados en las costuras UV.

Torneo Florent
fuente
Debido a que la pregunta es antigua, en su lugar te preguntaré :-) ¿Por lo que entiendo, simplemente tener información de dependencia para cada vértice no fue lo suficientemente bueno para Rusia?
Andreas
Esto fue para mi proyecto de tesis el año pasado, terminé yendo por el camino tonto y usando agregados atómicos enteros, escalados para maximizar la precisión, y luego normalizándolos para flotar vectores. No se pudo encontrar una manera de enumerar caras alrededor de cada vértice sin asignar el peor de los casos y usar contadores atómicos para construir las listas de todos modos. Es probable que sea ineficaz como el infierno, pero todavía tiene un par de órdenes de magnitud de aceleración de la versión CPU y una marca de primera clase, así que estaba bastante contento con él :)
Russ