Converting between float2 and float4

In unity3D you frequently have quantities given as float4, homogeneous coordinate system, however when working with 2D games it's useful to convert that to float2 and back:

float2 to_float2(float4 i) {
  return i.xy / i.w;

float4 to_float4(float2 i, float4 rest) {
  return float4(
    i.xy * rest.w,

This converts nicely back and forth, rest variable is used to restore original z and w values.

On the other hand, we can just directly cast float3 to float2 without having to worry about w coordinate (still in some cases you might care about z coordinate).

Accessing Player position in shaders

Let's say that we export players position into global shader properties:

public void LateUpdate() {

In order to produce following effect (background is darkened dynamically around the player character):

We can use following vertex and fragment shader in unity3d:

// Global property
float3 _playerOffset;

struct v2f {
  float4 pos : POSITION;
  float green : COLOR;

v2f vert(appdata_img v) {
  v2f o;
  o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

  float4 v_pos = mul(UNITY_MATRIX_MV, v.vertex);
  float dist = length(float2(_playerOffset) - to_float2(v_pos)); = (dist <= 1) ? dist/2 : 0.5;
  return o;

float4 frag(v2f i) : COLOR {
  return float4(0.2, + 0.2, 0.2, 1);

What about limited speed of light?

Assume that speed of light is low, and think about this. When vertex has constant velocity and you want to render it on the screen, that vertex should not be rendered in it's original location. Given that vertex is some distance away from the player, it takes time for the light to reach the player.

We can compute quantities like:

$$ \vec{v} = \text{vertex velocity} $$

I should note that $\vec{v}$ has same direction as $\vec{c}$.

$$ \vec{a} = \text{from player to proper vertex location} $$

$$ \beta = \arccos{\frac{\vec{v}\cdot\vec{a}}{\left|\vec{v}\right|\cdot\left|\vec{a}\right|}} $$

If we think about the time it takes light to reach player from visible position. In that same time, vertex has moved from visible position to proper position. Thus:

$$ \frac{\left|\vec{c}\right|}{\left|\vec{b}\right|} = \frac{\text{vertex velocity}}{\text{speed of light}} $$

This problem falls under SSA solution of triangles, you can read about it on a wiki page: Solution of triangles.

$$ \sin{\gamma} = \frac{\left|\vec{c}\right|}{\left|\vec{b}\right|}\sin{\beta} $$

$$ \alpha = 180^0 - \beta - \gamma $$

And finally length of $\vec{c}$ is given by $$ \left|\vec{c}\right| = \left|\vec{a}\right| \frac{\sin{\gamma}}{\sin{\alpha}} $$

Putting it all together, it looks like this:


I should note that special relativity effects are not included in any shape or form.

You can see the final demo in here: UniDemo1.html (Jump with space on keyboard).

What's wrong with this demo?

If you jump off the cliff, visible object will move far back to the left. We need a way to keep history of objects in memory, that way we can switch between two (or more) movement velocities from back in time.

Also, some special relativity would be a nice touch.


Related Posts