Skip to content

Instantly share code, notes, and snippets.

@charlieroberts
Created March 20, 2018 13:18
Show Gist options
  • Select an option

  • Save charlieroberts/2e8b75a0e34f4327767408a5ef0f8537 to your computer and use it in GitHub Desktop.

Select an option

Save charlieroberts/2e8b75a0e34f4327767408a5ef0f8537 to your computer and use it in GitHub Desktop.
a quick tutorial on using repetition, translation, and deformation with SDFs.

SDF part II

Begin with what we did last class: sdf.glslify.notes.md · GitHub

… but ignore the perlin noise so that we just have a sphere on the screen.

Simple translation

How do we move a primitive around the screen? We can do this by applying an offset to the current point being sampled by our raytracer. Remember that this point is passed to our doModel function in our shader. Our typical doModel for rendering a sphere is as follows:

vec2 doModel( vec3 p ) {
  float radius = 1.;
  float dist = length(p) - radius;

  return vec2( dist, 0. );
}

Offsetting this is done below:

vec2 doModel( vec3 p ) {
  float radius = 1.;
  vec3 translatedPoint = p + vec3( 1., 0., 0. ); // move on x-axis
  float dist = length( translatedPoint ) - radius;

  return vec2( dist, 0. );
}

Repetition

We’ll add the following function to our shader for repeating a point over space:

vec3 opRep( vec3 p, vec3 c ) {
    vec3 q = mod(p,c)-0.5*c;
    return q;
}

In the above code, p represents the point being sampled by our raytracer. c determines how often we want to repeat our primitive over space.

To repeat our sphere along the x and y axis using this function:

vec2 doModel( vec3 p ) {
  vec3 repeatedPoint = opRep( p, vec3( 3., 3., 0. );
  float radius = 1.;
  float dist = length( repeatedPoint ) - radius;

  return vec2( dist, 0. );
}

Use another shape (a torus)

Here’s the signed distance function for a torus:

float sdTorus( vec3 p, vec2 t ){
  vec2 q = vec2(length(p.xz)-t.x,p.y);
  return length(q)-t.y;
}

The second vec2 determines the outer radius of the ring and the inner radius (the donut hole). To use that in our doModel function:

vec2 doModel( vec3 p ) {
  float torus = sdTorus( p, vec2( 1., .5 ) );
  return vec2( torus, 0. );
}

Twist a shape

We can twist a point (rotate it along two axes) with the following function:

vec3 opTwist( vec3 p, float amount ){
    float c = cos(amount*p.y);
    float s = sin(amount*p.y);
    mat2  m = mat2(c,-s,s,c);
    vec3  q = vec3(m*p.xz,p.y);
    return q;
}

To use that in our doModel:

vec2 doModel( vec3 p ) {
  vec3 twisted = opTwist( p, 2. );
  float torus = sdTorus( twisted, vec2( 1., .5 ) );
  return vec2( torus, 0. );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment