Implicit Helpers
Implicit functions take an xyz position as input, and return a value. Polyscope contains several helper features to directly visualize implicit functions by taking a callable as input and automatically invoking it as needed. This can be a much easier way to interface with volumetric and inherently implicit data. In particular, Polyscope contains a built-in renderer to render images of levelsets of implicit functions.
Batch Evaluation
In principle, an implicit function takes a single xyz position as input, and returns a single value. However, Polyscope might need to invoke the callback function millions of times, which can introduce excessive performance overhead, especially if the underlying function is being evaluated on a GPU, or due to cross-language binding overhead. For this reason, we use batch evaluation, to perform many evaluations with each invocation and amortize the overhead.
Implict helpers expect you to pass a callback function which takes as input an (N,3)
numpy array of query positions, and returns an (N,)
array of evaluated values (or returns (N,3)
array of colors for color functions). N
is the number of queries, which will be determined as-needed internally by Polyscope.
Directly Rendering Implicit Isosurfaces
Polyscope can directly render images of an isosurface of an implicit function in space, from the current viewport or from a defined camera view. The resulting renders are added as Render Images, which support material shading, colormapping, transparency, and depth-compositing with other content in the scene.
Not a Fast Renderer
There is a long history of highly efficient real-time implicit shaders and ray marchers in computer graphics. Polyscope’s built-in implicit ray marching renderer is not fast, and it never will be! It should be viewed as a debugging tool, not a real-time renderer. Its design fundamentally prioritizes ease-of-use over speed; for instance even if your function is defined on the GPU, Polyscope will perform many expensive CPU round-trips to render it, doing multiple evaluations of the given implicit function.
If you want real-time implicit rendering, you will need to perform that rendering outside of Polyscope. However, the resulting renders can still be added to Polyscope as a Render Image to take advantage of Polyscope’s functionality. You can even use direct GPU interop (beta feature!) to do so with minimal realtime overhead.
Example:
import polyscope as ps
import numpy as np
ps.init()
# define some implicit functions
def sphere_sdf(pts): # takes [N,3] query pos array, returns [N,] SDF values
res = np.linalg.norm(pts, axis=-1) - 1.
return res
def color_func(pts): # takes [N,3] query pos array, returns [N,3] color values
A = np.ones_like(pts) * 0.3
A[:,0] = np.cos(3*pts[:,0])**2
return A
# render from the current view
ps.render_implicit_surface("sphere sdf", sphere_sdf,
mode='sphere_march', enabled=True)
ps.render_implicit_surface_color("sphere sdf", sphere_sdf, color_func,
mode='sphere_march', enabled=True)
ps.show()
Implicit Render Options
The most important option to set the mode
for the renderer. There are two choices:
mode='sphere_march'
should be used if your implicit function is a Signed Distance Function (SDF). That is, its magnitude gives the distance to the surface, or at least a conservative bound on the distance. This allows the renderer to take large steps based on the SDF value.mdoe='fixed_step
must be used if your implicit function is not necessarily an SDF. This forces to renderer to take many small steps, which is inefficient but always works for sufficiently small step size.
The following options can be set as additional keywords arguments to any render function
camera_view
aCameraView
structure (or the string name of one). If given, the render will be performed from the viewpoint of that camera, and the resulting render image will be added to the cameracamera_parameters
aCameraParameters
object defining the view to render from. If is not passed, then the current viewport will be used, unless thecamera_view
arg is set, in which case that camera will be used insteaddim
2-tuple of ints giving the dimension to render at (if rendering from the current view, this may be omitted, and the viewport resolution will be used)subsample_factor
int, ifdim
is being set automatically, downscale it by this factor (e.g.subsample_factor=2
means usedimX/2
anddimY/2
)miss_dist
float, an absolute value for how far a ray must go to be considered a missmiss_dist_relative
float, a relative value for how far a ray must go to be considered a miss (default: 20.)hit_dist
float, an absolute value for how close a ray must go to be considered a hithit_dist_relative
float, a relative value for how close a ray must go to be considered a hit (default: 1e-4)step_factor
float, a small tolerance factor applied to step sizes (default: 0.99)normal_sample_eps
float, a relative numerical parameter for finite differences normals (default: 1e-3)step_size
float, the absolute step size to used forfixed_step
marchingstep_size_relative
float, the relative step size to used forfixed_step
marching (default: 1e-2)n_max_steps
int, the maximum number of steps to take (default: 1024)
For options which have an absolute and relative version, you may specify either but not both. Relative values are defined with respect to the scene length scale.
Render Depth Images
Render a depth Render Image of the 0 isosurface of a function. The resulting surface will be shaded with materials and lighting.
render_implicit_surface(name, func, mode, color=None, **kwargs)
func
a batch callable defining the function whose 0-levelset we will rendermode
is the render mode, one of'sphere_march', 'fixed_step'
- see the bulleted listing above for other arguments common to all render functions
The 0 isolevel is always used. To render a different isolevel, add a constant offset shift to your function before passing it in.
See the “Batch Evaluation” popout at the top for a description of the expected signatures for function arguments.
Render Scalar Images
Render a scalar Render Image of the 0 isosurface of a function. The resulting surface will be shaded with materials and lighting. An additional implicit function defines a scalar value which will be shaded with colormapping on the isosurface.
render_implicit_surface_scalar(name, func, func_scalar, mode, **kwargs)
func
a batch callable defining the function whose 0-levelset we will renderfunc_scalar
another batch callable defining a scalar function which will be evaluated on the isosurface and displayed with color mappingmode
is the render mode, one of'sphere_march', 'fixed_step'
- see the bulleted listing above for other arguments common to all render functions
The 0 isolevel is always used. To render a different isolevel, add a constant offset shift to your function before passing it in.
See the “Batch Evaluation” popout at the top for a description of the expected signatures for function arguments.
Render Color Images
Render a color Render Image of the 0 isosurface of a function. The resulting surface will be shaded with materials and lighting. An additional implicit function defines a color value which will be shaded with colormapping on the isosurface.
render_implicit_surface_color(name, func, func_color, mode, **kwargs)
func
a batch callable defining the function whose 0-levelset we will renderfunc_color
another batch callable defining a color function which will be evaluated on the isosurface and displayed with color mappingmode
is the render mode, one of'sphere_march', 'fixed_step'
- see the bulleted listing above for other arguments common to all render functions
The 0 isolevel is always used. To render a different isolevel, add a constant offset shift to your function before passing it in.
See the “Batch Evaluation” popout at the top for a description of the expected signatures for function arguments.
Render Raw Color Images
Render a raw color Render Image of the 0 isosurface of a function. An additional implicit function defines a color value which will be used on the isosurface. The difference between color and raw color images is that plain Color
rendered images apply lighting and material shading to the colors (like a SurfaceMesh
would), whereas RawColor
images really just directly display the given color as the pixel values.
render_implicit_surface_raw_color(name, func, func_color, mode, **kwargs)
func
a batch callable defining the function whose 0-levelset we will renderfunc_color
another batch callable defining a color function which will be evaluated on the isosurfacemode
is the render mode, one of'sphere_march', 'fixed_step'
- see the bulleted listing above for other arguments common to all render functions
The 0 isolevel is always used. To render a different isolevel, add a constant offset shift to your function before passing it in.
See the “Batch Evaluation” popout at the top for a description of the expected signatures for function arguments.
Implicit Volumes
In addition rendering isosurfaces, Polyscope can automatically register the implicit function as a volumetric grid of values. See the volume grid scalar quantity for details.