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?