Houdini 11 VEX VEX functions

Samples geometry in the scene and returns information from the shaders of surfaces that were sampled.

  1. int sample_geometry(vector origin, vector sample, float time, ...)

Overview

The sample_geometry operation in VEX is used to distribute a single sample point on geometry objects in the scene, and to execute the surface shader at that point. The operation is similar to the trace and gather functions in that it accepts a variadic argument list of shader outputs to be exported by the operation. However, sample_geometry is different from raytracing functions in that it does not actually send a ray into the scene to determine where shaders should be run. The origin and sample parameters have different meanings depending on the type of distribution. time can be used with motion blur to distribute sample points in time as well as in space.

Area Distribution

In this mode, points will be distributed over multiple primitives according to their area. More samples will be placed on primitives with large surface areas than on primitives with small surface areas. The sample parameter should contain uniform random variables in the range of 0 to 1. The origin parameter has no effect.

Parametric Distribution

In this mode, primitive and subdivision IDs along with parametric surface coordinates are mapped to surface positions. This mode is useful when trying to maintain a coherent set of surface positions (for example, in a point cloud) across multiple frames because the same primitive ID, subdivision ID, s, and t coordinates map to similar surface positions even when a mesh is deforming. The sample parameter contains the s and t coordinates (in the first and second components), while the origin parameter contains the primitive and subdivision IDs (again, in the first and second components).

Solid Angle Distribution

This mode is similar to the “area” mode, except that points on a particular primitive are distributed according to solid angle rather than area. More specifically, samples will be distributed according to hemispherical coverage relative to origin. The sample parameter should contain uniform random variables in the range of 0 to 1.

Details

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.

KeywordValue typeDescriptionDefault
samples int/floatNumber of rays to send. (Gather only)1
anglefloat

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

0
distribution string

Determines the sampling distribution. For Gather,

  • cosine – Rays are distributed by the cosine (diffuse) function over the hemisphere.

  • uniform – Rays are distributed uniformly over the hemisphere

For sample_geometry,

  • area – Samples are distributed by primitive area

  • parametric – Samples are distributed by primitive ID, subdivision ID, and parametric surface coordinates (s, t).

  • solidangle – Samples are distributed either by primitive area or by primitive area and solid angle subtended by the primitive.

"cosine"
biasfloat Ray-tracing bias.0.001
SIDint

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
rayweightfloat

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
raystylestring

The type of rays you are sending. Mantra will use raystyle to determine both the default raytracing mask and bounce limit used for ray termination.

  • reflect – Sending reflection rays. Mantra will use the reflection mask and reflection limit to terminate raytracing.

  • refract – (default) Sending refraction rays. Mantra will use the refraction mask and refraction limit to terminate raytracing.

  • diffuse – Sending diffuse rays. Mantra will use the diffuse limit for diffuse rays.

  • shadow – Sending shadow rays. Mantra will not modify the raytracing level and will trace against shadowmask if inside a shadow or light shader.

  • nolimit – Sending reflection rays with no limit on the number of raytracing bounces. Mantra will still increment the raytracing level when sending nolimit rays.

"refract"
scopestring 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.
maxdistfloat

The maximum distance to search for objects. This can be used to limit the search of objects to nearby objects only. If the maxdist given is negative, then it will act as if there is no maximum distance.

-1
samplebasefloat

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
variancevarstring

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 vm_variance property as a threshold). If more samples are required, the algorithm takes samples up to the specified maximum ray samples.

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 vm_dorayvariance is enabled. Otherwise, only the min ray samples (or an explicitly supplied "samples" value) are used for antialiasing of the gather loop.

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:

KeywordValue typeDescription
ray:originvector The origin of the ray (defined in else clause also).
ray:directionvector The direction of the ray (defined in else clause also).
ray:lengthfloatThe distance to the first surface which was hit by the ray.
ray:areafloatThe total surface area of all the geometry in the raytracing scope.
ray:solidanglefloatThe 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 keyword argument to pass a light name pattern to limit the set of lights used to illuminate the hit surface. This allows the tracing surface to control the lighting of the hit surface. The "scope:default" value will cause the lightmask argument to use the default light mask for the current context - as if the argument were not specified.

    ..., "lightmask", "hotlights*");
    

Example

The following example demonstrates how sample_geometry can be used to illuminate one surface from another. Rather than using a light source, illumination is gathered from other surfaces in the scene named /obj/sphere_object* and will illuminate any surfaces with the geolight surface shader assigned.

A few observations about the shader:

  • The ray:solidangle output is used to scale back geometry sample contributions by the solid angle subtended by the hit surface. This ensures that the result of using sample_geometry will match physically based irradiance.

  • The trace instruction is used for shadowing

  • High-quality sampling patterns from newsampler and nextsample are used for antialiasing

surface
geolight(int nsamples = 64)
{
    vector        sam;
    vector        clr, pos;
    float        angle, sx, sy;
    int                sid;
    int                i;

    sid = newsampler();

    Cf = 0;
    for (i = 0; i < nsamples; i++)
    {
        nextsample(sid, sx, sy, "mode", "qstrat");
        sam = set(sx, sy, 0.0);
        if (sample_geometry(P, sam, Time,
                    "distribution", "solidangle",
                    "scope", "/obj/sphere_object*",
                    "ray:solidangle", angle, "P", pos, "Cf", clr))
        {
            if (!trace(P, normalize(pos-P), Time,
                        "scope", "/obj/sphere_object*",
                        "maxdist", length(pos-P)-0.01))
            {
                clr *= angle / (2*PI);
                clr *= max(dot(normalize(pos-P), normalize(N)), 0);
            }
            else
                clr = 0;
        }
        Cf += clr;
    }
    Cf /= nsamples;
}