Home Reference VEX VEX functions 

gather vex function

Sends rays into the scene and returns information from the shaders of surfaces hit by the rays.

Overview

You can use VEX’s gather loop statement to send rays into the scene and gather the resulting information.

gather(vector origin, vector direction, ...)
{
// Statements for rays that hit other surfaces
}
else
{
// Statements for rays which didn't hit any surface
}

Arguments

After the origin and direction arguments, any additional arguments are interpreted as keyword/value pairs.

gather(origin, dir, "samples", 100) {
...
}

There are three types of arguments you can pass to the gather loop: arguments controlling how to send rays, what information to pass to the shaders of other surfaces hit by the ray, and what information to import back from each spent ray.

Controlling how to send the rays

These argument pairs control how the gather statement sends rays into the scene.

KeywordValue typeDescription

samples

int/float

Number of rays to send.

angle

float

The distribution angle (specified in radians). Rays will be distributed over this angle.

distribution

string

Determines the sampling distribution. Possible values are “cosine” or “uniform”.

bias

float

Ray-tracing bias.

rayweight

float

A hint to mantra to indicate the relative contribution of this ray to the final shading. This value is used by the ray clip threshold to limit sending of rays (similar to ray bounce).

raystyle

string

The type of rays you are sending. Mantra will use one of three different hard limits for ray bounce determination based on this value.

  • reflect – Sending reflection rays.

  • global – Sending rays for global illumination.

  • refract – (default) Sending refraction rays.

scope

string

A list of objects which can be hit by the rays.

maxdist

float

The maximum distance to search for objects. This can be used to limit the search of objects to nearby objects only.

samplebase

float

Typically, rays are distributed over the surface of the micro-polygon being shaded. This argument can be used to control the area. A value of 0 will force all rays to be sent from the same point. A value of 1 will cover the entire micro-polygon.

variancevar

string

The name of a VEX variable to use for variance anti-aliasing.

This variable must be imported from the hit surface, so it must be in the list of imported names (see “importing information back from the ray” below). If the named variable is not imported, this option will be ignored.

See also “pipeline option” below.

Sending information to the hit surface’s shader

Using a keyword in the form "send:name", value, you can pass data from the originating surface to surfaces which are intersected by the ray. These arguments pass any values you want.

gather(P, dir, "send:N", normalize(N)) { ... }

You can extract this passed data on the receiving end (that is, in the surface being hit by the ray) with the rayimport function. The first argument is the name (without the send: prefix) and the second argument is a variable in which to store the imported value.

int rayimport(string name, type &value)

rayimport returns 1 if the value was imported successfully.

Importing information back from the ray

You can specify names of global or exported variables to import from the hit shader in the form "varname", &var, typically including Cf (color vector of surface hit) and Of (opacity vector of surface hit).

vector hitcf;
gather(P, dir, "bias", 0.01, "Cf", hitcf) {...}

In addition, you can import the following special keywords to get information about the ray itself:

KeywordValue typeDescription

ray:origin

vector

The origin of the ray (defined in else clause also).

ray:direction

vector

The direction of the ray (defined in else clause also).

ray:length

float

The distance to the first surface which was hit by the ray.

By default, Houdini composites the global variables using opacity blending. In some cases, it’s more useful to get the value from the closest surface (regardless of whether it’s transparent). You can use the special samplefilter keyword with a string value of either closest or opacity to control whether the value of a global is from the closest surface or opacity blended.

When the samplefilter keyword is encountered in the argument list, all following import variables will use the specified filtering mode. You can specify multiple samplefilter arguments in a single gather statement to filter different variables in different ways.

gather(P, dir,
"samplefilter", "opacity",
"Cf", hitCf,
"Of", hitOf,
"samplefilter", "closest",
"P", hitP,
"N", hitN)

Pipeline option

As you specify variables, you can intersperse pipeline keyword options to control where in the pipeline to fill out read/write variables. The value can be one of surface, atmosphere, or displacement. You can specify the pipeline option multiple times. Each use of the option affects any variables specified after it (up to the next usage of pipeline if any).

gather(p, d, "pipeline", "surface", "Cf", surfCf,
"pipeline", "atmosphere" "Cf", fogCf, "P", hitP)

Example

Here are two shaders which communicate through gather.

This shader sends rays into the scene. It sends 1.234 in a message labeled exportvalue. Since the surface hit by the rays may not have an exported parameter called amp, it’s important to initialize this variable before the gather loop.

surface
sendray(vector background=0; int nsamples=16)
{
vector hitcf;
float ss, tt, amp;
amp = 0;
gather(P, dir,
"bias", 0.01,
"angle", radians(5),
"samples", nsamples,
"samplebase", 1,
"distribution", "cosine",
"send:exportvalue", 1.234,
"Cf", hitcf,
"s", ss,
"t", tt,
"amp", amp)
{
Cf += set(ss, tt, 0);
amp = 0;
}
else
{
Cf += background;
}
Cf *= 1.0/nsamples;
}

The following shader imports values which were sent to it by the gather loop. The exported parameter can be imported by the gather loop.

surface
hitsurf(export float amp=1)
{
float sendbias = 0;
float sendsamples = 0;
float sendvalue = 0;
if (!rayimport("bias", sendbias))
printf("Error importing the bias\n");
if (!rayimport("samples", sendsamples))
printf("Error importing the samples\n");
if (!rayimport("exportvalue", sendvalue))
printf("Error importing the send:exportvalue\n");
Cf = amp*noise(P);
}