Création de normales de sommet partagées sur GPU

9

J'ai surtout réussi à porter une implémentation de Marching Cubes du CPU vers des shaders de calcul OpenGL, mais je n'ai pas encore abordé les normales et je me demande la meilleure façon de procéder.

Mon implémentation traite spécifiquement des champs à valeurs binaires (j'essaie de modéliser des fonctions fractales 3D qui n'ont pas encore d'estimateur de distance), donc les méthodes de gradient et de différences directes ne fonctionneront pas. J'ai partagé des sommets en fonctionnement, et mon implémentation CPU utilise la méthode de Quilez décrite ici pour accumuler des normales de face sur chaque sommet voisin.

Je pourrais simplement porter cette implémentation sur un autre shader, mais le problème que je vois avec cela est le nombre massif d'atomes nécessaires. Puisque nous ne pouvons utiliser l'atomique que sur des types entiers scalaires, et je ne peux pas penser à un moyen de regrouper 3 entiers signés en 1 de manière sommable, cela signifie 3 axes * 3 sommets = 9 ajouts atomiques par invocation de shader. Ils seront répartis dans la mémoire bien sûr, ce n'est donc pas comme frapper un seul compteur atomique 9 fois, mais cela semble encore beaucoup.

L'autre alternative est d'exécuter un shader invocation par polygone et de construire la liste normale des faces (je pourrais probablement emballer à x10y10z10 de cette façon), puis un shader par sommet pour accumuler toutes les normales des faces voisines. Ce serait un énorme porc de mémoire cependant, l'espace de stockage des indices de visage aurait besoin de 12 int par sommet pour faire face au pire des cas. Il y a aussi le problème de l'écriture dans ce stockage sans recourir à nouveau à l'atomique pour déterminer combien de faces ont déjà été écrites sur un sommet particulier.

Quelqu'un a-t-il de meilleures idées sur la façon de procéder?

russ
la source

Réponses:

5

Pour une solution nVidia uniquement, vous pouvez utiliser des intrinsèques d'ajout atomique à virgule flottante (comme NvInterlockedAddFp32). Déverrouillage intrinsèque du GPU dans HLSL | Développeur NVIDIA

J'ai essayé cela sur 80.000 vertex mesh et c'est assez rapide (quelque chose comme 1 ou 2 ms sur une GTX980M, si je me souviens bien)

Méfiez-vous simplement de la compilation de vos shaders en version pour que les intrinsèques fonctionnent (en raison du bug / limitation nvidia)

Méfiez-vous également des séparations de sommets (en raison de discontinuités UV par exemple), vous devrez les gérer ou bien vous aurez des bords durs indésirables aux coutures UV.

Florent Tournade
la source
Parce que la question est ancienne, je vais vous demander à la place :-) Pour ce que je comprends, avoir simplement des informations d’adjonction pour chaque sommet n’était pas suffisant pour russ?
Andreas
C'était pour mon projet de thèse l'année dernière, j'ai fini par utiliser la voie muette et en utilisant des ajouts atomiques entiers, augmentés à l'échelle pour maximiser la précision, puis normalisés pour flotter des vecteurs. Impossible de trouver un moyen de répertorier les visages autour de chaque sommet sans allouer d'espace dans le pire des cas et utiliser des compteurs atomiques pour construire les listes de toute façon. C'est probablement inefficace comme l'enfer mais j'ai encore quelques ordres de grandeur d'accélération de la version CPU et une marque de première classe, donc j'en étais assez content :)
russ