2014-04-13 13 views
5

W przypadku kursu graficznego wdrażamy system cząstek w WebGL. Wykonanie obliczeń symulacji cząstek w JavaScript byłoby dość powolne, nasz profesor chce, abyśmy zrobili symulację cząstek na GPU.System cząsteczek za pomocą webgl

Aby przeprowadzić symulację cząstek, wyobrażamy sobie, że przesyłamy bufor wierzchołków zawierający nasze dane cząstek (położenie, prędkość, masę, itp.), A następnie, że mój moduł do cieniowania wierzchołków wykonuje kilka obliczeń dla symulacji i zapisuje wyniki do inny bufor wierzchołków, reprezentujący następny stan cząsteczek. Następnie mogę renderować moje cząstki używając gl.POINTS przy użyciu innego programu cieniującego do renderowania.

Wydaje się przekształcić zwrotne, które uczę stąd: http://open.gl/feedback

Wydaje się jednak, jak przekształcić zwrotne nie jest obecnie zawarte w WebGL. This blog post mówi, że sprzężenie zwrotne transformacji wyjdzie z WebGL 2.0. Rzeczywiście, gdy wypróbowuję takie instrukcje, jak gl.beginTransformFeedback;, pojawia się błąd informujący, że metoda nie jest zdefiniowana.

W jaki sposób mam przeprowadzić symulację cząstek w WebGL, jeśli informacja zwrotna o transformacji nie jest dostępna?

Odpowiedz

5

Niektóre propozycje

sposób można uzyskać większą elastyczność wyświetlania używając quady zamiast punktów. Można w zasadzie umieścić w danych wierzchołków dla każdego coś cząstek jak

//localX, localY, data for particle, data for particle, ... 
    -1,  -1, gravityForParticle0, velocityForParticle0, etc.., 
     1,  -1, gravityForParticle0, velocityForParticle0, etc.., 
    -1,  1, gravityForParticle0, velocityForParticle0, etc.., 
     1,  1, gravityForParticle0, velocityForParticle0, etc.., 
    -1,  -1, gravityForParticle1, velocityForParticle1, etc.., 
     1,  -1, gravityForParticle1, velocityForParticle1, etc.., 
    -1,  1, gravityForParticle1, velocityForParticle1, etc.., 
     1,  1, gravityForParticle1, velocityForParticle1, etc.., 
    -1,  -1, gravityForParticle2, velocityForParticle2, etc.., 
     1,  -1, gravityForParticle2, velocityForParticle2, etc.., 

więc dane dla każdej cząstki jest identyczny dla każdego wierzchołka każdego quad. Innymi słowy trzeba

unit vertex #0, particle0 data 
unit vertex #1, particle0 data 
unit vertex #2, particle0 data 
unit vertex #3, particle0 data 

unit vertex #0, particle1 data 
unit vertex #1, particle1 data 
unit vertex #2, particle1 data 
unit vertex #3, particle1 data 

unit vertex #0, particle2 data 
unit vertex #1, particle2 data 
unit vertex #2, particle2 data 
unit vertex #3, particle2 data 

Teraz można obracać, skalować i zorientowania quad w swoim cieniującego i przesunięcie go jednak chcesz, coś, czego nie można zrobić z POINTS.

Ponadto, jeśli twój system cząsteczek jest deterministyczny (jak w przypadku każdej cząstki opiera się wyłącznie na czasie), możesz umieścić wszystkie swoje zmienne w atrybutach i mundurach i po prostu przekazać czas jako mundur.

Możesz zobaczyć an example of this kind of system here. Cząstki te działają całkowicie na GPU. Jedyne, co minęło, to czas i matryce do projekcji. Zajmują się orientowaniem cząstek w 3D, zmieniają kolor z upływem czasu, obracają się z czasem, pozycją z prędkością i przyspieszeniem w czasie, a nawet animacją tekstur w czasie (zobacz liczby w przykładzie).

Oprócz tych technik, jeśli system cząsteczek nie jest deterministyczny, co oznacza, że ​​masz stan, który zmienia każdą klatkę, możesz zapisać stan do tekstury, dołączając teksturę do obiektu bufora ramki. Jeśli twoja maszyna obsługuje tekstury zmiennoprzecinkowe, możesz napisać do RGBA/FLOAT i odczytać tę teksturę jako dane wejściowe w shaderze wierzchołków lub fragmentów w kolejnym wywołaniu rysowania.

There's an example here. Możesz nawet wyświetlić teksturę używaną do obliczeń.

+0

Metoda quadowa z pewnością przyda się w moim projekcie. Nasz system cząsteczek jest niedeterministyczny, więc twój drugi przykład jest niezwykle pomocny. – newprogrammer

0

Możesz przekazać początkową prędkość i wektory przyspieszenia jako atrybuty do wierzchołka modułu cieniującego i przekazać czas jako jednolitą, która jest zwiększana w każdej pętli ramki o 1/60. Jeśli na przykład masz stałego przyspieszenia, można użyć tej formuły ruchu obliczyć różnicę położenia w vertex shader:

dx = vInitial.x + (0.5 * acceleration.x * time^2) 
dy = vInitial.y + (0.5 * acceleration.y * time^2) 
dz = vInitial.z + (0.5 * acceleration.z * time^2) 

i oczywiście:

positionNew = positionOld + (dx, dy, dz) 

Następnie można pomnożyć wektor positionNew modelować i wyświetlić matrycę rzutowania, aby uzyskać końcową pozycję danego wierzchołka.