HowTo:Turn a continuous function into a stepped function

From POV-Wiki
Jump to navigation Jump to search

Overview

Normally, functions are evaluated so that they transition smoothly from start to finish with no apparent pixelation. However, sometimes you want functions to evaluate in such a way such that the interpolation between steps is apparent. For instance, maybe you are rendering the graph of a function and you want to make it obvious to the viewer what the function's intervals are. In this case you want to use a stepped function.

The initial function

Before you can create a stepped function, you have to define the function the stepped function is based upon. For this example we will create a function that is used as a pattern in a pigment. Let's define a simple gradient that extends along the vector, x + y.

#declare ThePattern = function(x, y, z) { x + y }

This is equivalent to a gradient pattern. We could also have used this:

#declare ThePattern = function { pattern { gradient x + y } };

Now that we've defined the initial function we can create the stepped function.

Creating the stepped function

The basic idea behind creating a stepped function is to evaluate the original function in such a way that the values get rounded somehow. We determine how and how much a function gets rounded by specifying how many steps, or intervals, we want for every unit of POV space. We then multiply the function by this number, round it to the nearest integer, and divide the function by the same number you multiplied it by. Let's say we wanted three steps. Then, we would multiply the whole function by three, round it to the nearest integer, and divide by three.

#declare SteppedPattern = function { int(3 * ThePattern(x, y, z)) / 3 };

Let's interpolate across ten steps instead of three. In this case, do as follows.

#declare SteppedPattern = function { int(10 * ThePattern(x, y, z)) / 10 };

Viewing the results

The next step is to render the image. For that we will use the following scene which contains our initial function and our stepped function.

#default { finish { ambient 1 } }
background { rgb z * 0.5 }
camera { location <0, 0, -10> look_at 0 angle 35 }

#declare ThePattern = function { x + y };
#declare SteppedPattern = function { int(10 * ThePattern(x, y, z)) / 10 };

// Original pattern:
box
{
  <-1, -2, 0>, <1, 2, .1>
  pigment
  {
    function { ThePattern(x, y, z) }
    color_map { [0 rgb 0][1 rgb 1] }
    scale 2
  }
  translate -x * 1.1
}

// Stepped pattern:
box
{
  <-1, -2, 0>, <1, 2, .1>
  pigment
  {
    function { SteppedPattern(x, y, z) }
    color_map { [0 rgb 0][1 rgb 1] }
    scale 2
  }
  translate x * 1.1
}

The results should look something like this:

Stepped function pattern.png


The pattern on the left is the original, smooth pattern. The pattern on the right is the same pattern, rounded to ten intervals.