# IsosurfaceReference

See the `isosurface`

tutorial for more about working with *isosurfaces*.

New in version 3.8 a `potential`

pattern has been added to define a pattern based on the *potential* field of a `blob`

or `isosurface`

object. See also: Potential Pattern.

The syntax basics are as follows:

isosurface { function { FUNCTION_ITEMS } [contained_by { SPHERE | BOX }] [threshold FLOAT_VALUE] [accuracy FLOAT_VALUE] [max_gradient FLOAT_VALUE] [evaluate P0, P1, P2] [open] [max_trace INTEGER] | [all_intersections] [polarity on | +VALUE | off | -VALUE] [OBJECT_MODIFIERS...] }

Isosurface default values:

contained_by : box{-1,1} threshold : 0.0 accuracy : 0.001 max_gradient : 1.1 polarity : off

Since *isosurfaces* are defined by a user supplied `function { ... }`

it must be specified as the first item of the `isosurface`

statement. Here you place all the mathematical functions that will describe the surface.

The `contained_by`

*object* limits the area where POV-Ray samples for the surface of the function. This container can either be a `sphere`

or a `box`

both of which use the standard POV-Ray syntax. If nothing is specified a default `box`

, as noted above, will be used. See additional usage examples below:

contained_by { sphere { CENTER, RADIUS } } contained_by { box { CORNER1, CORNER2 } }

Using `threshold`

specifies how much strength, or substance to give the `isosurface`

. The surface appears where the `function`

value equals the `threshold`

value. See above for the listed default value.

The `isosurface`

resolver uses a recursive subdivision method. This subdivision goes on until the length of the interval where POV-Ray finds a surface point is less than the specified `accuracy`

. See above for the listed default value. Be aware that smaller values produce more accurate surfaces, but takes longer to render.

POV-Ray can find the first intersecting point between a ray and the `isosurface`

of any continuous function if the maximum gradient of the function is known. To that end you can specify a `max_gradient`

for the function. See above for the listed default value. When the `max_gradient`

used to find the intersecting point is too high, the render slows down considerably. Conversely, when it is too low, artifacts or holes may appear on the isosurface, and in some cases when it is way too low, the surface does not show at all. While rendering the `isosurface`

POV-Ray stores the found gradient values and issues a warning, if these values are either higher or much lower than the specified `max_gradient`

value:

Warning: The maximum gradient found was 5.257, but max_gradient of the isosurface was set to 5.000. The isosurface may contain holes! Adjust max_gradient to get a proper rendering of the isosurface.

Warning: The maximum gradient found was 5.257, but max_gradient of the isosurface was set to 7.000. Adjust max_gradient to get a faster rendering of the isosurface.

For best performance you should specify a value close to the real maximum gradient.

*Isosurfaces* can also dynamically adapt the used `max_gradient`

. To activate this technique you have to specify the `evaluate`

keyword followed by these three parameters:

**P0:**the minimum`max_gradient`

in the estimation process.**P1:**an over-estimating factor. That is, the`max_gradient`

is multiplied by the*P1*parameter.**P2:**an attenuation parameter of 1 or less

In this case POV-Ray starts with the `max_gradient`

value *P0* and dynamically changes it during the render using *P1* and *P2*. In the evaluation process, the *P1* and *P2* parameters are used in
quadratic functions. This means that over-estimation increases more rapidly with higher values and attenuates more rapidly with lower values. It should also be noted that when using dynamic `max_gradient`

, there can be artifacts or holes.

If you are unsure what values to use, just start a render *without* using `evaluate`

to get a value for the `max_gradient`

, then use that value with `evaluate`

like this:

**P0:**`max_gradient * Min_Factor`

**P1:**`sqrt(max_gradient/(max_gradient * Min_Factor))`

**P2:**should be 1 or less use 0.7 as a good starting point.

Where *Min_Factor* is a float between 0 and 1 to reduce the `max_gradient`

to a *minimum* `max_gradient`

. The ideal value for *P0* would be the average of the found maximum gradients, but we do not
have access to that information. A good starting point for *Min_Factor* is 0.6

If there are artifacts or holes in the `isosurface`

, you can just increase *Min_Factor* and / or *P2*. For Example: when the first run gives a *found* `max_gradient`

of 356, start with:

#declare Min_factor= 0.6; isosurface { ... evaluate 356*Min_factor, sqrt(356/(356*Min_factor)), 0.7 //evaluate 213.6, 1.29, 0.7 ... }

This method is only an approximation of what happens internally, but it gives faster rendering speeds with the majority of *isosurfaces*.

When the `isosurface`

is not fully contained within the `contained_by`

object, there will be a cross section. When this happens, you will see the surface of the container. Using the `open`

keyword, these cross section surfaces are removed, and the inside of the `isosurface`

becomes visible.

**Note:** Using `open`

slows down the render speed, and it is not recommended for use with CSG operations.

*Isosurfaces* can be used in CSG shapes since they are solid finite objects - if not finite by themselves, they are through the cross section with the container. By default POV-Ray searches only for the first surface which the ray intersects. However, when using an `isosurface`

in CSG operations, the other surfaces must also be found. Consequently, the keyword `max_trace`

followed by an integer value, must be added to the `isosurface`

statement. To check for all surfaces, use the keyword `all_intersections`

instead. With `max_trace`

it only checks until that number is reached.

**Note:** The current implementation has a *limit* of 10 *intersections* in all cases.

By default, the inside of an `isosurface`

is defined as the set of all points inside the `contained_by`

shape where the function values are below the threshold. New in version 3.8 this can be changed via the `polarity`

keyword. Specifying a *positive* setting or `on`

will instead cause function values *above* the threshold to be considered inside. Specifying a *negative* setting or `off`

will give the default behavior.