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 }
After the origin and direction arguments, any additional arguments are interpreted as keyword/value pairs.
gather(origin, dir, "samples", 100) { ... }
Note
If you specify 0 samples, it will still take at least 1 sample.
Variadic Gather Arguments
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 sent ray.
Controlling how to send the rays
These argument pairs control how the gather statement sends rays into the scene.
| Keyword | Value type | Description | Default |
|---|---|---|---|
samples | int/float | Number of rays to send. (Gather only) | 1 |
angle | float | The distribution angle (specified in radians). Rays will be distributed over this angle. (Gather only) | 0 |
distribution | string | Determines the sampling distribution. For Gather,
For sample_geometry,
| "cosine" |
bias | float | Ray-tracing bias. | 0.001 |
SID | int | Sample identifier to be passed to the called shader. If the calling shader has used SID to generate samples, it can be useful to pass the modified sample identifier to the called shader so that it can begin sampling at the specified offset. This value will be used to initialize the SID global in the hit surface. | 0 |
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). | 1 |
raystyle | string | The type of rays you are sending. Mantra will use
| "refract" |
scope | string | A list of objects which can be hit by the rays. When specified, scope overrides the default scope that would have been selected for the given raystyle. The "scope:default" value will cause the scope argument to use the default scope for the current context - as if the argument were not specified. | |
maxdist | float | The maximum distance to search for objects. This can be used to limit the search of objects to nearby objects only. If the | -1 |
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. (Gather only) | 0 |
variancevar | string | The name of a VEX export variable to use for variance anti-aliasing. The renderer compares the value with adjacent micropolygons in micropolygon rendering to decide what shading points need additional samples (using 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. Variance antialiasing puts more samples in areas of the image with high variance, for example a sharp shadow edge. It is only used when |
See also the Pipeline option section in the gather function help.
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:
| Keyword | Value type | Description |
|---|---|---|
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. |
ray:area | float | The total surface area of all the geometry in the raytracing scope. |
ray:solidangle | float | The estimated solid angle subtended by all geometry in the raytracing scope. For large objects close to or enclosing the ray origin, this may be a very poor estimate while for individual primitives the estimate can be very good. |
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)
Light mask
lightmask
| You can use the
..., "lightmask", "hotlights*");
|
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) { float amp; amp = 0; Cf = 0; gather(P, N, "bias", 0.01, "angle", radians(15), "samples", nsamples, "samplebase", 1, "distribution", "cosine", "send:exportvalue", 0.8, "amp", amp) { Cf += amp; amp = 0; } else { Cf += background; } Cf *= 1.0 / nsamples; Of = 1; }
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 sendvalue = 0; if (!rayimport("exportvalue", sendvalue)) printf("Error importing the send:exportvalue\n"); amp = sendvalue; Cf = 1; Of = 1; }