Jak użyć potoku graficznego do renderowania danych wolumetrycznych na podstawie funkcji gęstości?

12

Oba graficzne interfejsy API (OpenGL i DirectX) opracowują dobrze zdefiniowany potok, w którym można zaprogramować kilka etapów. Te programowalne etapy wymagają przyjęcia określonej minimalnej ilości danych i powinny wykonywać na nim dobrze określony zakres operacji i generować pewne określone minimalne dane wyjściowe, aby dane mogły być poprawnie przekazywane do następnego etapu. Wydaje się, że te rurociągi są zaprojektowane do pracy z ograniczoną ilością typów danych geometrycznych, które w przypadku D3D i OGL są danymi wierzchołków i współrzędnymi tekstury.

Ale jeśli podano przypadek, gdy aplikacja, którą planuję zrobić, nie używa wierzchołków (lub nawet wokseli) do reprezentowania swoich danych geometrycznych i nie wykonuje dokładnie przekształceń, rzutów, rasteryzacji lub interpolacji itp., Takie ograniczenia interfejsów API lub rurociąg utrudnia.

Czy istnieje sposób, w jaki możemy zmienić potok grafiki w taki sposób, aby funkcjonalność tego, co każdy etap robi z danymi, oraz rodzaj danych, które są wyprowadzane na każdym etapie, zostały zmienione na moją korzyść? Jeśli nie, to czy istnieje sposób, w jaki mogę użyć „surowych” funkcji API do budowy własnego potoku? Jeśli nie, proszę podać, dlaczego nie jest to możliwe.

EDYCJA : Moja aplikacja używa funkcji gęstości do reprezentowania geometrii. Funkcja ma wartość w każdym punkcie przestrzeni. Dzielę fragment aparatu na siatkę 3d, każdy blok może być wyświetlany jako piksel. W każdym bloku integruję funkcję gęstości i sprawdzam, czy jej wartość jest większa niż wartość wymagana. Jeśli tak, to zakłada się, że coś istnieje w tym bloku i że piksel odpowiadający temu blokowi jest renderowany. więc teraz w moim rendererze chcę przekazać funkcję (którą reprezentuję za pomocą łańcucha) do sprzętu graficznego zamiast danych wierzchołków w buforach wierzchołków. oznacza to również, że moduł cieniujący wierzchołki nie będzie miał wierzchołków do przekształcenia w przestrzeń klipu homogenicznego, a moduł cieniujący fragmenty nie otrzymuje informacji o pikselach. zamiast tego teraz większość wyszukiwania i oceny odbywa się na piksel.

The Light Spark
źródło
Czy „funkcja gęstości funkcji” jest tautologią?
Pharap
@Pharap, to była literówka. po prostu „funkcja desity”, która reprezentuje obecność „materii” w przestrzeni.
Iskra światła
2
Wygląda na to, że po prostu chcesz zbudować izosurface, co jest dobrze zbadanym problemem. Czy widziałeś http.developer.nvidia.com/GPUGems3/gpugems3_ch07.html lub przeszukiwałeś Metaballs, wizualizację chmury punktów, ekstrakcję izosurface lub rendering objętości? Jakiego rodzaju wydajności potrzebujesz, będzie to miało ogromny wpływ na wybór techniki, której szukasz, w połączeniu ze złożonością twoich obliczeń. Myślę, że przekonasz się również, że piksel spowoduje migotanie, gdy kamera się porusza, i wymagany będzie subpiksel.
Patrick Hughes,

Odpowiedzi:

18

Możesz bezwzględnie użyć GPU do renderowania danych wolumetrycznych.

Ponieważ chcesz ocenić zestaw funkcji na piksel na ekranie, prostym podejściem jest renderowanie trójkąta pełnoekranowego. To tylko jeden trójkąt, który obejmuje cały ekran (w rzeczywistości obejmuje więcej niż ekran, ponieważ ekran nie jest trójkątny, ale części poza ekranem są odrzucane przez GPU). Następnie możesz użyć modułu cieniującego piksele (który otrzymuje współrzędne ekranowe cieniującego piksela), aby skonstruować promień na podstawie głośności, ocenić funkcje, cokolwiek musisz zrobić.

(W przeciwieństwie do innych odpowiedzi, nie polecam modułu obliczeniowego, ponieważ brzmi to tak, jakbyś chciał wykonywać operacje na piksel, a pełnoekranowy moduł cieniujący + trójkąt + piksel jest na ogół bardziej wydajny niż moduł obliczeniowy - chociaż shadery obliczeniowe z pewnością również będą działać).

Trójkąt pełnoekranowy jest bardzo powszechny w grafice w czasie rzeczywistym dla operacji przetwarzania końcowego, więc prawdopodobnie możesz znaleźć wszystkie potrzebne informacje przy odrobinie googlingu.

BTW, może zainteresować Cię odczyt Rendering Worlds with Two Triangles autorstwa Iñigo Quíleza, wykład, który opisuje, jak renderować sceny 3D złożone z wykorzystaniem funkcji matematycznych (w szczególności pól odległości) przy użyciu pełnoekranowej techniki cieniowania pikseli.

Nathan Reed
źródło
Czy moduł cieniujący piksele pobiera dowolne dane wejściowe (takie jak ciągi znaków lub inne typy obiektów zdefiniowanych przez użytkownika), więc mogę przekazać moje funkcje?
Iskra światła
Wątpię, czy chciałbyś spróbować uruchomić analizator składni i / lub język na dowolnych ciągach funkcji na GPU, co byłoby niezręczne, ponieważ GPU nie są tak naprawdę ogólnego przeznaczenia. Najprawdopodobniej chcesz dynamicznie utworzyć sam moduł cieniujący w głównym kodzie, a następnie pozwolić systemowi graficznemu skompilować i uruchomić wynikowy moduł cieniujący.
Patrick Hughes,
@TheLightSpark Racja, nie przekazywałbyś ciągów do modułu cieniującego (języki cieniowania nawet nie mają typu łańcucha), chciałbyś wygenerować i skompilować kod modułu cieniującego dla pożądanych funkcji. W razie potrzeby można to zrobić w czasie wykonywania.
Nathan Reed
Zacząłem czytać twoją odpowiedź, wyobrażałem sobie monitor w kształcie trójkąta;) Czy zaletą jest użycie tylko jednego trójkąta zamiast dwóch, które pokrywają ekran bez odrzucania pikseli?
danijar
@danijar Tak, ma niewielką przewagę nad użyciem quada, ponieważ niektóre piksele wzdłuż przekątnej zostaną dwukrotnie zacienione, jeśli użyjesz quada pełnoekranowego. Z drugiej strony usuwanie pikseli poza ekranem jest bezpłatne, ponieważ rasterizer nie wygeneruje tych pikseli na początku.
Nathan Reed
6

Śledzenie promieni i inne techniki są zwykle wykonywane przy pomocy Compute Shaders, które Direct3D obsługuje od wydania D3D11, a OpenGL obsługuje od 4.3 (i dłużej dzięki OpenCL i niektórym zniekształceniom).

Sean Middleditch
źródło
5

Wygląda to tak, jakbyś chciał korzystać z modułu cieniującego GPU lub obiektu „Shader Storage Buffer”, aby ulepszyć potok zgodnie z potrzebami. Matematycy, naukowcy i inni ludzie, którzy szukają w GPU obliczeń dotyczących rzeczy, które nie tłumaczą się dokładnie na standardową grafikę, używają tego rodzaju rzeczy.

Mimo że współczesny potok grafiki jest bardzo elastyczny, programiści wciąż napotykają pewne ograniczenia. Funkcja shaderów obliczeniowych ułatwia nam jednak nie myśleć o etapach potoku, ponieważ jesteśmy przyzwyczajeni do myślenia o wierzchołkach i fragmentach. Nie jesteśmy już ograniczeni wejściami i wyjściami niektórych etapów rurociągu. Na przykład wprowadzono funkcję obiektu buforującego pamięć masową (SSBO) wraz z modułami obliczeniowymi, co daje dodatkowe możliwości wymiany danych między etapami potoku, a także umożliwia elastyczne wprowadzanie i wysyłanie danych dla modułów cieniujących.

http://community.arm.com/groups/arm-mali-graphics/blog/2014/04/17/get-started-with-compute-shaders

Jeśli to nie wskaże ci właściwego kierunku, czy mógłbyś rozwinąć swoją koncepcję, która nie pasuje do paradygmatu wierzchołek / fragment?

AAorris
źródło
Zredagowałem swoją odpowiedź, aby uwzględnić to, co robię. obliczenia cieniowania wydają się być odpowiedziami, ale po prostu powiedz mi, czy mogę zrobić coś jeszcze.
The Light Spark