Specjalny shadery względności w GLSL

11

Próbuję wdrożyć moduł cieniujący GLSL, który pomaga zrozumieć specjalną teorię względności Lorentza Transformation.

Weźmy dwóch obserwatorów bezwładnościowych Oi O'. Obserwator O'porusza się Oz prędkością obserwatora v=(v_x,0,0).

W przypadku opisu O'współrzędnych zdarzenie P' = (x',y',z',ct')przekształciło współrzędne(x,y,z,ct)= L (x',y',z',ct')

gdzie L jest macierzą 4x4 zwaną transformacją Lorentza, która pomaga nam zapisywać współrzędne zdarzenia P 'we Owspółrzędnych.

(po szczegóły patrz http://en.wikipedia.org/wiki/Lorentz_transformation#Boost_in_the_x-direction )

Zapisałem pierwszy wstępny moduł cieniujący wierzchołek, który stosuje transformację Lorentza, biorąc pod uwagę prędkość każdego wierzchołka, ale nie mogę uzyskać prawidłowego działania transformacji.

vec3 beta= vec3(0.5,0.0,0.0);
float b2 = (beta.x*beta.x + beta.y*beta.y + beta.z*beta.z )+1E-12; 
float g=1.0/(sqrt(abs(1.0-b2))+1E-12); // Lorentz factor (boost)
float q=(g-1.0)/b2;

//http://en.wikipedia.org/wiki/Lorentz_transformation#Matrix_forms
vec3 tmpVertex = (gl_ModelViewMatrix*gl_Vertex).xyz;
float w = gl_Vertex.w;

mat4  lorentzTransformation =
        mat4(
            1.0+beta.x*beta.x*q ,   beta.x*beta.y*q ,   beta.x*beta.z*q , beta.x*g ,
            beta.y*beta.x*q , 1.0+beta.y*beta.y*q ,   beta.y*beta.z*q , beta.y*g ,
            beta.z*beta.x*q ,   beta.z*beta.y*q , 1.0+beta.z*beta.z*q , beta.z*g ,
            beta.x*g , beta.y*g , beta.z*g , g
            );
vec4 vertex2 = (lorentzTransformation)*vec4(tmpVertex,1.0);


gl_Position = gl_ProjectionMatrix*(vec4(vertex2.xyz,1.0) );

Ten moduł cieniujący powinien mieć zastosowanie do każdego wierzchołka i wykonywać nieliniową transformację Lorentza, ale transformacja, którą wykonuje, wyraźnie różni się od tego, czego się spodziewałam (w tym przypadku skrócenie długości na osi x).

Czy ktoś już pracował nad specjalnym shaderem względności do gier 3D?

linello
źródło
W rzeczywistości jest to transformacja liniowa, a nie nieliniowa, jak twierdzi połączona wiki. Więc to, co widzisz, brzmi dobrze, jednak trudno powiedzieć na pewno, nie widząc tego.
Maik Semder
Możesz wypróbować ten moduł cieniujący w programie ShaderMaker, aby zobaczyć efekty, ale chciałbym osiągnąć ten efekt: spacetimetravel.org/relaflug/relaflug.html Tutaj powinniśmy zobaczyć skurcz długości na osi X, ale widzę nieprawidłowe skalowanie
linello
Czy faktycznie poruszasz kamerą? Link do spacetimetravle jest dostarczany z kodem źródłowym, może warto tam zajrzeć
Maik Semder
także prędkość 0,5 c / s jest nieco mała, spróbuj użyć czegoś większego niż 0,9, przykład używa 0,93 c / s i przesuń kamerę z tą prędkością
Maik Semder
Nie. Przypuszczam, że obserwator Opatrzy (0,0,0) w dół na oś z, podczas gdy obserwator O'porusza się Oz prędkością, v_xa opisane obiekty O'znajdują się w spoczynku. Wiem, że w tym module cieniującym wierzchołki transformacja jest stosowana tylko dla wierzchołków, więc deformacja linii jest tracona, ale po prostu chcę to zrozumieć i na początek to zrobić. Wydaje się, że gra Polynomial już dokonała tego rodzaju transformacji, ale znaleziony moduł cieniujący nie jest niczym interesującym, ponieważ otrzymuję takie same wyniki! bit.ly/MueQqo
linello

Odpowiedzi:

4

Aby wdrożyć skurcz Lorentza, najlepiej jest po prostu wyraźnie przeskalować obiekt o 1 / gamma wzdłuż kierunku ruchu.

Problem polega na tym, że transformacja Lorentza przemieszcza wierzchołki zarówno w czasie, jak i w przestrzeni, więc sama w sobie nie da ci, jak wygląda poruszający się obiekt w określonym momencie. Aby to zrobić, musisz najpierw przekształcić cały obiekt, a następnie wykonać „przekrój” równolegle do osi przestrzeni, jak na tym schemacie:

Wykres czasoprzestrzenny skurczu Lorentza

Aby to obliczyć naprawdę, trzeba efektywnie wykonać raytrace w 4D, przecinając linię świata wierzchołka z hiperpłaszczyzną 3D bieżącego momentu w ramce odniesienia obserwatora. Uważam, że efektem tego jest po prostu skalowanie o 1 / gamma.

(Aby zyskać dodatkowe uznanie, weź pod uwagę fakt, że obserwator nie zobaczyłby całego obiektu w jednym momencie: zobaczyliby go za pomocą promieni świetlnych. Musisz przeciąć linię świata wierzchołek z przeszłym stożkiem światła obserwatora. To faktycznie zmienia wyniki znacząco: obiekt oddalający się od ciebie będzie wyglądał na skrócony, ale obiekt poruszający się w twoją stronę będzie wyglądał na wydłużony, a obiekt poruszający się na boki zostanie obrócony - patrz obrót Penrose'a-Terrella po więcej.)

Nathan Reed
źródło
Ok, ale co jeśli zmienię czas w symulacji? Traktuję czas jako jednolity pływak do przepłynięcia spoza modułu cieniującego, czy powinien on poprawnie zdeformować obiekt w czasie?
linello
Jeśli czas jest stały dla każdej klatki, to bierzesz trójwymiarowy wycinek czasu świata 4D, więc tak, to, co powiedziałem powyżej, dotyczy.
Nathan Reed
Nie rozumiem również, czy muszę implementować aberrację relatywistyczną oddzielnie od transformacji Lorentza.
linello
@linello Jeśli zależy ci na aberracji, wygląda na to, że potrzebujesz bardziej wyrafinowanej wersji tego, którą opisałem w ostatnim akapicie - to znaczy przecinamy linię świata wierzchołka z dawnym stożkiem światła obserwatora i przesuń wierzchołek do punktu przecięcia lokalizacja przestrzenna. Myślę, że powinno to być wykonalne w module cieniującym wierzchołki. Transformacja Lorentza byłaby zaangażowana tylko w ustawienie linii świata wierzchołka. Zauważ również, że jeśli obiekt przyspiesza, obraca się itp., To linia świata jest zakrzywiona.
Nathan Reed