Tworzenie wspólnych normalnych wierzchołków na GPU

9

Przeważnie udało mi się przenieść implementację Marching Cubes z CPU do shaderów obliczeniowych OpenGL, ale jeszcze nie poradziłem sobie z normami i zastanawiam się, jak to zrobić.

Moja implementacja zajmuje się konkretnie polami o wartości binarnej (próbuję modelować funkcje fraktalne 3D, które nie mają jeszcze estymatora odległości), więc metody różnic i gradientów do przodu nie będą działać. Dzielę działające wierzchołki, a moja implementacja procesora wykorzystuje opisaną tutaj metodę Quilez do gromadzenia normalnych twarzy na każdym sąsiednim wierzchołku.

Mógłbym po prostu przenieść tę implementację na inny moduł cieniujący, ale widzę problem z ogromną liczbą potrzebnych atomów. Ponieważ możemy używać atomów tylko na skalarnych typach liczb całkowitych, i nie mogę wymyślić sposobu na spakowanie 3 podpisanych liczb całkowitych w 1 w sposób sumowalny, oznacza to, że 3 osie * 3 wierzchołki = 9 dodatków atomowych na wywołanie modułu cieniującego. Będą one oczywiście rozrzucone w całej pamięci, więc nie jest to 9-krotne uderzenie w pojedynczy licznik atomowy, ale nadal wydaje się, że to cholernie dużo.

Inną alternatywą jest uruchomienie wywołania modułu cieniującego dla wielokąta i zbudowanie listy normalnych twarzy (prawdopodobnie mógłbym spakować do x10y10z10 w ten sposób), a następnie modułu cieniującego na wierzchołek, aby zgromadzić wszystkie normalne sąsiednie twarze. Byłby to jednak olbrzymi świnia pamięci, miejsce do przechowywania indeksów twarzy wymagałoby 12 int na wierzchołek, aby poradzić sobie z najgorszym przypadkiem. Istnieje również problem z tym, jak zapisać w tym magazynie, bez uciekania się do atomów, aby dowiedzieć się, ile twarzy zostało już zapisanych w danym wierzchołku.

Czy ktoś ma lepsze pomysły, jak to zrobić?

Russ
źródło

Odpowiedzi:

5

W przypadku rozwiązania wyłącznie nVidia można użyć zmiennoprzecinkowych atomowych elementów wewnętrznych (takich jak NvInterlockedAddFp32) Odblokowywanie wewnętrznych układów GPU w HLSL | Deweloper NVIDIA

Próbowałem tego na siatce 80 000 wierzchołków i jest dość szybki (coś takiego jak 1 lub 2 ms w GTX980M, jeśli dobrze pamiętam)

Tylko uważaj na kompilowanie shaderów w wydaniu dla wewnętrznych funkcji (z powodu błędu / ograniczenia NVIDIA)

Uważaj również na pęknięcia wierzchołków (na przykład z powodu nieciągłości UV), będziesz musiał sobie z nimi poradzić, w przeciwnym razie będziesz mieć niechciane twarde krawędzie w szwach UV.

Florent Tournade
źródło
Ponieważ pytanie jest stare, zadam ci zamiast tego :-) Bo co rozumiem, po prostu posiadanie informacji o adjencency dla każdego wierzchołka nie było wystarczające dla Russ?
Andreas
To było dla mojego projektu dyplomowego w zeszłym roku. Skończyło się na głupim sposobie i używaniu liczb całkowitych atomowych, skalowanych w górę, aby zmaksymalizować precyzję, a następnie normalizowaniu do wektorów swobodnych. Nie udało się znaleźć sposobu, aby wyświetlić listę twarzy wokół każdego wierzchołka bez przydzielenia najgorszego miejsca i użycia liczników atomowych do zbudowania list. Jest to prawdopodobnie nieefektywne jak cholera, ale wciąż dostałem kilka rzędów wielkości przyspieszenia z wersji procesora i znak pierwszej klasy, więc byłem z niego zadowolony :)
Russ