Uni development: simulating limited speed of light

Published 27 Apr 2014 by Emir Habul.

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,
    rest.zw
  );
}

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() {
  Shader.SetGlobalVector(
    "_playerOffset",
    playerTransform.position
  );
}

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));
  o.green = (dist <= 1) ? dist/2 : 0.5;
  return o;
}

float4 frag(v2f i) : COLOR {
  return float4(0.2, i.green + 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:

Demo

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.

Tags


CallGraphs with PerfTool

Published 07 Feb 2014 by Emir Habul.

Goal is to show callgraphs of any process

perf record -g ./foo
perf script | ./gprof2dot.py -f perf | dot -Tpng -o foo.png

This utility comes from jrfonseca's Gprof2Dot page, direct download link is: gprof2dot.py (local mirror).

Produces:

And test program

#include <stdio.h>

int sum = 0;
#define LOOP()                    \
  {                               \
    int j;                        \
    for (j = 0; j < 10000; j++) { \
      sum += j;                   \
    }                             \
  }

int f() { LOOP(); }
int d() { LOOP(); f(); }
int e() { LOOP(); f(); }
int c() { LOOP(); d(); LOOP(); e(); }
int b() { LOOP(); c(); }
int a() { LOOP(); c(); }

int main() {
  int i;
  for (i = 0; i < 10000; i++) {
    a();
    b();
  }
}

Tags


My jekyll installation for a personal website

Published 07 Feb 2014 by Emir Habul.

You'll find this post in your _posts directory - edit this post and re-build (or run with the -w switch) to see your changes! To add new posts, simply add a file in the _posts directory that follows the convention: YYYY-MM-DD-name-of-post.ext.

Compiling jekyll blog:

jekyll serve --detach
jekyll build --watch

Jekyll extensions

<script type="text/javascript"
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

\begin{equation} \sqrt{4} + 1 \ne 5 \frac{1}{2} \end{equation}

def print_hi(name)
  puts "Hi, #{name}"
end
print_hi('Tom')
#=> prints 'Hi, Tom' to STDOUT.

Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll's GitHub repo.

Tags