Erstellen gemeinsamer Scheitelpunktnormalen auf der GPU


9

Es ist mir größtenteils gelungen, eine Implementierung von Marching Cubes von der CPU auf OpenGL-Compute-Shader zu portieren, aber ich habe mich noch nicht mit Normalen befasst und mich gefragt, wie ich am besten vorgehen kann.

Meine Implementierung befasst sich speziell mit binär bewerteten Feldern (ich versuche, 3D-Fraktalfunktionen zu modellieren, die noch keinen Entfernungsschätzer haben), sodass Gradienten- und Vorwärtsdifferenzmethoden nicht funktionieren. Ich habe gemeinsame Scheitelpunkte, und meine CPU-Implementierung verwendet die hier beschriebene Quilez-Methode, um Gesichtsnormalen auf jedem benachbarten Scheitelpunkt zu akkumulieren.

Ich könnte diese Implementierung einfach auf einen anderen Shader portieren, aber das Problem, das ich dabei sehe, ist die enorme Anzahl der benötigten Atomics. Da wir Atomics nur für skalare Ganzzahltypen verwenden können und ich mir keine Möglichkeit vorstellen kann, 3 vorzeichenbehaftete Ints summierbar in 1 zu packen, bedeutet dies 3 Achsen * 3 Eckpunkte = 9 atomare Adds pro Shader-Aufruf. Sie werden natürlich im ganzen Gedächtnis verteilt sein, also ist es nicht so, als würde man neun Mal einen einzelnen Atomzähler treffen, aber es scheint immer noch verdammt viel zu sein.

Die andere Alternative besteht darin, einen Shader-Aufruf pro Polygon auszuführen und die Liste der Gesichtsnormalen zu erstellen (ich könnte wahrscheinlich auf diese Weise auf x10y10z10 packen), dann einen Shader pro Scheitelpunkt, um alle Normalen benachbarter Gesichter zu akkumulieren. Dies wäre jedoch ein enormer Speicherbedarf. Der Speicherplatz der Gesichtsindizes würde 12 int pro Scheitelpunkt benötigen, um den schlimmsten Fall zu bewältigen. Es gibt auch das Problem, wie man in diesen Speicher schreibt, ohne erneut auf Atomics zurückzugreifen, um herauszufinden, wie viele Gesichter bereits auf einen bestimmten Scheitelpunkt geschrieben wurden.

Hat jemand bessere Ideen, wie das geht?

Antworten:


5

Für eine reine nVidia-Lösung können Sie Gleitkomma-Atomic-Add-Intrinsics (wie NvInterlockedAddFp32) verwenden, um GPU-Intrinsics in HLSL | zu entsperren NVIDIA-Entwickler

Ich habe es mit 80.000 Vertex Mesh versucht und es ist ziemlich schnell (so etwas wie 1 oder 2 ms auf einer GTX980M, wenn ich mich richtig erinnere)

Achten Sie nur darauf, dass Sie Ihre Shader in der Version nicht kompilieren, damit die Intrinsics funktionieren (aufgrund eines NVIDIA-Fehlers / einer Einschränkung).

Achten Sie auch auf Scheitelpunktspaltungen (z. B. aufgrund von UV-Diskontinuitäten). Sie müssen damit umgehen, da Sie sonst unerwünschte harte Kanten an UV-Nähten haben.


Weil die Frage alt ist, werde ich dich stattdessen fragen :-) Für was ich verstehe, war es für russ nicht gut genug, nur Adjencency-Informationen für jeden Scheitelpunkt zu haben?
Andreas

Dies war für mein Diplomarbeitsprojekt im letzten Jahr. Am Ende ging ich einfach nur dumm vor und verwendete ganzzahlige atomare Additionen, die zur Maximierung der Präzision skaliert und dann auf Float-Vektoren normalisiert wurden. Es konnte keine Möglichkeit gefunden werden, Gesichter um jeden Scheitelpunkt herum aufzulisten, ohne Platz im ungünstigsten Fall zuzuweisen und Atomlisten zu verwenden, um die Listen trotzdem zu erstellen. Es ist wahrscheinlich höllisch ineffizient, aber ich habe immer noch ein paar Größenordnungen schneller von der CPU-Version und eine erstklassige Note bekommen, also war ich damit zufrieden genug :)
russ
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.