This article contains the currently supported API for interacting with World Machine from your Lua scripts within the Code device.
As the bindings are continually developed, this reference material will be updated to stay current.
Overview
This API reference is only for the Host script language. You will also need to write one or more kernels in your compute language to create a device.
All World Machine bindings are exposed in the ‘wm’ library. To use any of the top-level commands below, make sure you access them with the ‘wm’ prefix. For example, ‘wm.parameter()’.
Sandboxing
To allow for secure sharing of plugin devices between users, the Lua scripting session is sandboxed:
- Your script has no access to the system or external data.
- Your script cannot persist information outside of the device build process.
- The compute kernels have no access to any other data than that provided via the scripting.
- The lua math and string libraries are available. No other built-ins are provided.
- The World Machine plugin API *is* accessible.
Future versions may relax the sandboxing for custom devices that are not shared with others.
Datatypes
A variety of custom datatypes are created by the World Machine library.
buffer: A raw collection of bytes. Can be used to supply general memory to your compute kernel, or when accessing the underlying data of an input such as a heightfield. Your kernel should accept this as a float* parameter (or other relevant type).
image: An Image datatype, as defined in OpenCL. This may be more convenient than accessing a raw buffer, and some API functions will only return images. The image will be a 2D four channel RGBA texture. Your kernel must access as an image2d_t parameter.
In addition, standard Lua datatypes are used:
value: This is a Lua built-in integer or floating point value. Your kernel can accept either and WM will convert as appropriate.
table: A Lua table, which is simply a collection of values.
string: A Lua string.
A few additional notes:
- If a function takes a slot value, it should be provided an integer.
- If a function takes a name, it should be provided a string.
- The extended datatypes have reference semantics. For example, that means that assigning one buffer to a new buffer variable does not copy the buffer – they will both refer to the same object.
Definitions
Some values defined within the library are meant to be identifiers rather than be manipulated. Providing these values allows WM to know what kind of data you are referring to.
Packet types
You can pass these identifiers to createBuffer or createImage, among other places, to create the correct types. They are a table defined at ‘wm.packet’.
wm.packet.hf -- A single channel heightfield image
wm.packet.rgb -- A 3-channel rgb image.
Data types
These are values used to communicate how to interpret a raw buffer. They are a table defined at ‘wm.type’. These are unused in the current API.
wm.type.byte -- 8bit unsigned integer data
wm.type.int -- 32bit
wm.type.int64 -- 64bit
wm.type.float -- 32bit floating point
wm.type.vec2 -- float vector2
wm.type.vec3 -- float vector3
wm.type.vec4 -- float vector4
wm.type.half -- 16bit floating point
wm.type.half3 -- 3 x 16bit floats
Inputs
Functions to take data from the input ports on the device, as well as the current parameters. The slot should be a number starting at zero for the first input.
buffer wm.inputBuffer(slot)
image wm.inputImage(slot)
value wm.inputValue(slot)
image wm.mask()
value wm.parameter(name)
value wm.parm(name) -- A convenience short alias for the above
Inputs of either heightfield or bitmap type can be taken as images or buffers, using either of the first two functions above as needed. The returned result will be of the type shown and can be used or passed to other functions.
Note that if you take a bitmap input as a buffer, the data is 3 channels of 16bit floating point, which takes special consideration to access inside of an OpenCL compute kernel.
Creation
Create new memory buffers or images for use by your compute kernels.
- If no type is specified, the default is a heightfield.
- If no dimensions are specified, the current world render size is used.
image wm.createImage(type, dims)
buffer wm.createBuffer(type, dims)
buffer wm.createRawBuffer(bytes)
Context Functions
Several functions are built-in to allow you to gain access to the build context your device is invoked within.
Worldspace
image wm.worldspace()
Generate a image containing the the xy world-space coordinates for this build, in the red and green channels. The blue and alpha channels are unused and set to zero.
The image values are unnormalized 32bit floats. They correspond exactly to the render extents defined in your project settings.
This is very useful to allow your compute kernel to understand what point in the world each pixel corresponds to! You will often use this, or the devicespace() function, to easily access this information.
If you output this image directly as a bitmap, it would look like this:
Devicespace
image wm.devicespace()
Devicespace is the world-space coordinate transformed by the device’s placement. The placement includes rotation, translation, and any connected domain distortion input.
The RGBA image is divided into two pairs of channels. The image values are unnormalized 32bit floats with real numbers.
- The RG channels contains the (X,Y) distorted coordinates
- The BA channels contains the undistorted (X,Y) device coordinates.
It looks like this, visualized:
Generally you will only need the RG channels. Device space is very useful for generator-type devices that want to make a pattern or some other output that can be placed into the world.
World Context
Retrieve a table containing the current render extent information.
table wm.context()
The table has the following members:
int dimX, dimY — Dimensions in pixels of the render extent
float x0, y0, x1, y1 — World render extent corners
float originX, originY — Placement origin
float rotate2D — Placement rotation in degrees
Outputs
Send data to an output port.
wm.output(data, port)
The port should be a number, starting at zero for the first output.
The port configuration determines the acceptable datatype to send. For example, a heightfield output must contain a buffer or image. Possible types of your data include:
hf : image, buffer
rgb : image, buffer
text : string
param : value, string
Compute Kernels
To perform operations on the GPU, use the runKernel function in the wm library.
wm.runKernel(kernelname/kernelobject, arg1, arg2, ...)
The first parameter must be a string containing the name of the compute kernel, while the following arguments should be buffers, images, or values. The types must match the type defined in your kernel function.
Currently, there is no way to define the local workgroup size of a kernel.
Other Functions
Progress Reporting
wm.progress(percent)
wm.progress(current, total)
You can specify the build progress as a floating point value from 0..1 or as current, total as integers.
There is currently no way to check if the user has requested the build to cancel.
Start the discussion at forum.world-machine.com