Criando normais de vértice compartilhados na GPU


9

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?

Respostas:


5

Para uma solução exclusiva da nVidia, você pode usar intrínsecos atômicos de adição de ponto flutuante (como NvInterlockedAddFp32) Desbloqueando intrínsecos da GPU no HLSL | Desenvolvedor NVIDIA

Eu tentei isso em 80.000 malhas de vértice e é bastante rápido (algo como 1 ou 2 ms em uma GTX980M, se bem me lembro)

Apenas tenha cuidado ao compilar seus shaders na versão para que os intrínsecos funcionem (devido a limitação / bug da nvidia)

Também tenha cuidado com as divisões de vértices (devido a descontinuidades de UV, por exemplo), você terá que lidar com elas ou então terá arestas duras indesejadas nas costuras de UV.


Como a pergunta é antiga, em vez disso, pedirei a você :-) Pelo que entendi, simplesmente ter informações de adjência para cada vértice não era bom o suficiente para russ?
Andreas

Este foi para o meu projeto de tese no ano passado, acabei seguindo de maneira burra e usando adições atômicas inteiras, escalando para maximizar a precisão e normalizando para flutuar vetores. Não foi possível descobrir uma maneira de listar as faces ao redor de cada vértice sem alocar o pior caso possível e usar contadores atômicos para criar as listas de qualquer maneira. É provavelmente ineficiente como o inferno, mas eu ainda tenho um par de ordens de aceleração magnitude da versão CPU e uma marca de primeira classe, então eu estava bastante feliz com ele :)
russ
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.