Специальный реляционный шейдер в GLSL

11

Я пытаюсь реализовать шейдер GLSL, который помогает понять специальное преобразование Лоренца.

Давайте возьмем два ориентированных по оси инерциальных наблюдателя Oи O'. Наблюдатель O'движется с наблюдателем Oсо скоростью v=(v_x,0,0).

Когда описывается в терминах O'координат, событие P' = (x',y',z',ct')изменило координаты(x,y,z,ct)= L (x',y',z',ct')

где L - матрица 4x4, называемая преобразованием Лоренца, которая помогает нам записать координаты события P 'в Oкоординатах.

(подробности смотрите http://en.wikipedia.org/wiki/Lorentz_transformation#Boost_in_the_x-direction )

Я записал первый предварительный вершинный шейдер, который применяет преобразование Лоренца с учетом скорости к каждой вершине, но я не могу заставить преобразование работать правильно.

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) );

Этот шейдер должен применяться к каждой вершине и выполнять нелинейное преобразование Лоренца, но преобразование, которое он выполняет, явно отличается от того, что я ожидал (в данном случае сокращение длины по оси x).

Кто-нибудь уже работал над специальным шейдером относительности для 3D-видеоигр?

linello
источник
Это на самом деле линейное преобразование, а не нелинейное, как вики вы связали состояния. То, что вы видите, звучит нормально, однако трудно сказать наверняка, не видя этого.
Майк Земдер
Вы можете попробовать этот шейдер в ShaderMaker, чтобы увидеть эффекты, но я бы хотел добиться этого эффекта: spacetimetravel.org/relaflug/relaflug.html Здесь мы должны увидеть сокращение длины по оси x, но я вижу неправильное масштабирование
linello
Вы на самом деле двигаете камеру? Ссылка spacetimetravle поставляется с исходным кодом, возможно, стоит взглянуть туда
Maik Semder
также скорость 0,5 с / с немного мала, попробуйте использовать что-то большее, чем 0,9, в примере используется 0,93 с / с и перемещайте камеру с этой скоростью
Maik Semder
Нет, я полагаю, что наблюдатель Oв (0,0,0) смотрит вниз по оси z, в то время как наблюдатель O'движется Oсо скоростью, v_xа описанные объекты O'находятся в покое. Я знаю, что в этом вершинном шейдере преобразование применяется только для вершин, поэтому деформация линий теряется, но я просто хочу сначала понять и заставить это работать. Кажется, что игра Polynomial уже произвела преобразования такого рода, но шейдер, который я нашел, не представляет ничего интересного, потому что я получаю те же результаты! bit.ly/MueQqo
linello

Ответы:

4

Чтобы реализовать сжатие Лоренца, лучше всего просто явно масштабировать объект на 1 / гамма вдоль направления движения.

Проблема в том, что преобразование Лоренца смещает вершины как во времени, так и в пространстве, поэтому само по себе оно не даст вам того, как движущийся объект выглядит в определенный момент времени. Чтобы сделать это, вы должны сначала преобразовать весь объект, а затем пройти через него «срез» параллельно пространственным осям, как на этой диаграмме:

Сжатие пространства-времени Лоренца

Чтобы вычислить это по-настоящему, вам нужно эффективно провести трассировку лучей в 4D, пересекая мировую линию вершины с трехмерной гиперплоскостью текущего момента времени в системе отсчета наблюдателя. Я полагаю, что результат этого будет таким же, как простое масштабирование на 1 / гамма.

(Для дополнительной оценки, примите во внимание тот факт, что наблюдатель фактически не видел бы весь объект в один момент времени: они увидели бы его с помощью световых лучей. Таким образом, вам нужно было бы пересечь мировую линию вершина с последним световым конусом наблюдателя, что на самом деле значительно меняет результаты: объект, удаляющийся от вас, будет выглядеть укороченным, но объект, движущийся к вам, будет выглядеть вытянутым, а объект, движущийся в сторону, будет вращаться - см. вращение Пенроуза-Террелла для большего.)

Натан Рид
источник
Хорошо, но что, если я изменю время внутри симуляции? Я отношу время к равномерному плавающему значению, которое должно передаваться извне шейдера, это должно правильно деформировать объект во времени?
linello
Если время является постоянным для каждого кадра, то вы берете трехмерный отрезок времени 4-мерного мира, так что да, то, что я сказал выше, справедливо.
Натан Рид
Я также не понимаю, нужно ли мне применять релятивистскую аберрацию отдельно от преобразования Лоренца.
linello
@linello Если вам небезразлична аберрация, похоже, вам нужна более сложная версия этого, которую я описал в последнем абзаце - то есть пересечение мировой линии вершины с прошлым световым конусом наблюдателя и перемещение вершины к точке пересечения. пространственное расположение. Это должно быть выполнимо в вершинном шейдере, я думаю. Преобразование Лоренца будет участвовать только в настройке мировой линии вершины. Также обратите внимание, что если объект ускоряется, вращается и т. Д., То мировая линия искривляется.
Натан Рид