Consegui na maioria das vezes transportar uma implementação de Marching Cubes da CPU para os shaders de computação OpenGL, mas ainda não resolvi os normais e me pergunto a melhor maneira de fazer isso.
Minha implementação lida especificamente com campos com valores binários (estou tentando modelar funções fractal 3D que ainda não possuem um estimador de distância), para que os métodos de diferenças de gradiente e de avanço não funcionem. Compartilhei vértices em funcionamento e minha implementação de CPU usa o método de Quilez descrito aqui para acumular normais de face em cada vértice vizinho.
Eu poderia simplesmente portar essa implementação para outro shader, mas o problema que vejo com isso é o grande número de átomos necessários. Como só podemos usar atômicos em tipos inteiros escalares, e não consigo pensar em uma maneira de empacotar 3 entradas assinadas em 1 de maneira resumida, isso significa 3 eixos * 3 vértices = 9 adições atômicas por invocação de shader. Eles estarão espalhados por toda a memória, é claro, então não é como acertar um único contador atômico 9 vezes, mas ainda parece muito.
A outra alternativa é executar uma chamada de sombreador por polígono e criar a lista de faces normais (eu provavelmente poderia compactar para x10y10z10 dessa maneira) e, em seguida, um sombreador por vértice para acumular todas as normais das faces vizinhas. Porém, isso seria um enorme problema de memória, pois o espaço de armazenamento dos índices de face precisaria de 12 int por vértice para lidar com o pior caso. Há também o problema de como gravar nesse armazenamento sem recorrer novamente aos atômicos para descobrir quantas faces já foram gravadas em um vértice específico.
Alguém tem alguma idéia melhor de como fazer isso?