I'm trying to implement a GLSL shader which helps understanding special relativity Lorentz Transformation.

Let's take two axis-aligned inertial observer O and O' . The observer O' is in motion w.r.t observer O with velocity v=(v_x,0,0).

When described in terms of O' coordinates, an event P' = (x',y',z',ct') has transformed coordinates (x,y,z,ct)= L (x',y',z',ct')

where L is a 4x4 matrix called Lorentz transformation which helps us writing the coordinates of event P' in O coordinates.

(for details look http://en.wikipedia.org/wiki/Lorentz_transformation#Boost_in_the_x-direction)

I've wrote down a first preliminary vertex shader that apply the Lorentz transformation given the velocity to every vertex, but I can't get the transformation to work correctly.

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;

vec3 tmpVertex = (gl_ModelViewMatrix*gl_Vertex).xyz;
float w = gl_Vertex.w;

mat4  lorentzTransformation =
            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) );

This shader should apply to every vertex and perform the non-linear Lorentz transformation, but the transformation it performs is clearly different from what I'd expect (in this case a length-contraction on x-axis).

Has somebody already worked on special relativity shader for 3D videogame?

  • \$\begingroup\$ It's actually a linear transformation, not non-linear, as the wiki you linked states. So what you see sounds ok, however, hard to say for sure without seeing it. \$\endgroup\$ Commented Jul 30, 2012 at 12:31
  • \$\begingroup\$ You can try this shader in ShaderMaker to see the effects, but what I'd want to achieve is this effect: spacetimetravel.org/relaflug/relaflug.html Here we should see the lenght contraction on x-axis but I see an incorrect scaling \$\endgroup\$
    – linello
    Commented Jul 30, 2012 at 13:09
  • \$\begingroup\$ Do you actually move the camera? The spacetimetravle-link comes with source code, might worth having a look there \$\endgroup\$ Commented Jul 30, 2012 at 13:48
  • \$\begingroup\$ also the speed 0.5 c/s is a bit small, try using something bigger than 0.9, the example uses 0.93 c/s and move the camera with that speed \$\endgroup\$ Commented Jul 30, 2012 at 14:04
  • \$\begingroup\$ No I suppose the observer O is in (0,0,0) looking down the z-axis while the observer O' is in motion w.r.t O with velocity v_x and the objects described for O' are at rest. I know that in this vertex shader the transformation are applied only for vertices so the deformation of lines is lost but I just want to understand and make work this at first. Seems that the game Polynomial already made transformations of this kind, but the shader I've found doesn't nothing interesting, because I get the same results! bit.ly/MueQqo \$\endgroup\$
    – linello
    Commented Jul 30, 2012 at 14:52

1 Answer 1


To implement Lorentz contraction, your best bet is probably just to explicitly scale the object by 1/gamma along the direction of motion.

The trouble is that the Lorentz transformation displaces vertices in the time direction as well as in space, so by itself it will not give you what a moving object looks like at a specific moment in time. To do that, you would have to first transform the whole object then take a "slice" through it parallel to the space axes, like in this diagram:

Lorentz contraction space-time diagram

To calculate this for real, you'd effectively have to raytrace in 4D, intersecting the world-line of the vertex with the 3D hyperplane of the current moment of time in the observer's reference frame. I believe the result of doing this is the same as simply scaling by 1/gamma.

(For extra credit, take into account the fact that an observer wouldn't actually see the whole object at a single moment in time: they'd see it using light rays. So you'd need to intersect the world-line of the vertex with the past light cone of the observer. This actually changes the results significantly: an object moving away from you will look shortened, but an object moving toward you will appear elongated and an object moving sidways will be rotated - see Penrose-Terrell rotation for more.)

  • \$\begingroup\$ Ok, but what if I'm changing the time inside the simulation? I treat time as a uniform float to be pass from outside the shader, this should deform the object in time correctly? \$\endgroup\$
    – linello
    Commented Aug 1, 2012 at 9:02
  • \$\begingroup\$ If time is a constant for each frame, then you're taking a 3D time-slice of the 4D world, so yes, what I said above holds. \$\endgroup\$ Commented Aug 1, 2012 at 17:03
  • \$\begingroup\$ I don't understand also if I have to implement relativistic aberration separately from the Lorentz transformation. \$\endgroup\$
    – linello
    Commented Aug 1, 2012 at 20:41
  • \$\begingroup\$ @linello If you care about aberration, it sounds like you need the more sophisticated version of this I described in the last paragraph - that is, intersect the vertex's world-line with the observer's past light cone, and move the vertex to the intersection point's spatial location. That should be doable in the vertex shader, I think. The Lorentz transform would be involved only in setting up the vertex's world-line. Also note that if the object is accelerating, rotating, etc. then the world-line is curved. \$\endgroup\$ Commented Aug 1, 2012 at 20:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .