Rx API

Rx API

July, 2009 (Updated May, 2012)

The Rx library allows writers of RiProcedural and Shading Language plugins to query internal state of the renderer, as well as access useful internal functions that would otherwise be difficult or impossible to duplicate. In order to use these functions, the header file "rx.h" must be included with the preprocessor directive #include.


Interfaces

A variety of C++ interfaces can be accessed from Rx by first obtaining a RixContext with RxGetRixContext, and then using this context to get the desired interface via RixContext::GetRixInterface with an interface id:

RixContext *RxGetRixContext();
RixInterface *RixContext::GetRixInterface(RixInterfaceId id);
typedef enum {
    k_RixThreadUtils,
    k_RixMessages,
    k_RixStats,
    k_RixGlobalData,
    k_RixThreadData,
    k_RixLocalData
} RixInterfaceId;

See the RixInterface API documentation for complete information.


Noise

RtInt RxNoise(int inDimension, float *in,
              int outDimension, float *out);
RtInt RxPNoise(int inDimension, float *in, float *period,
               int outDimension, float *out);
RtInt RxCellNoise(int inDimension, float *in,
                  int outDimension, float *out);

These functions allows DSOs to access PRMan's internal implementation of noise, including the nonperiodic, periodic, and cellular varieties. These functions take as input an array of inFloats, with dimensionality specified in inDimension (which can be 1 to 4). The output noise values is placed in out, which has dimensionality specified in outDimension. The period parameter for RxPNoise should be nonzero for periodic noise.


Texture Lookup

RtInt RxEnvironment(RtString filename, RtInt firstchannel,
                    RtInt nchannels, RtPoint dir0, RtPoint dir1, RtPoint dir2, RtPoint dir3,
                    RtFloat *result, ...);

RtInt RxShadow(RtString filename, RtInt firstchannel,
               RtPoint P0, RtPoint P1, RtPoint P2, RtPoint P3, RtFloat *result, ...);

RtInt RxTexture(RtString filename, RtInt firstchannel, RtInt nchannels,
                RtFloat s0, RtFloat t0, RtFloat s1, RtFloat t1, RtFloat s2, RtFloat t2,
                RtFloat s3, RtFloat t3, RtFloat *result, ...);

RtInt RxEnvironmentPoints(RtString filename, RtIntnPoints,
                          RtInt firstchannel, RtInt nchannels,
                          RtFloat *dir0, RtFloat *dir1, RtFloat *dir2, RtFloat *dir3,
                          RtFloat *result, ...);

RtInt RxShadowPoints(RtString filename, RtIntnPoints, RtInt firstchannel,
                     RtFloat *P0, RtFloat *P1, RtFloat *P2, RtFloat *P3, RtFloat *result, ...);

RtInt RxTexturePoints4(RtString filename, RtIntnPoints, RtInt firstchannel, RtInt nchannels,
                       RtFloat *s0, RtFloat *t0, RtFloat *s1, RtFloat *t1, RtFloat *s2, RtFloat *t2,
                       RtFloat *s3, RtFloat *t3, RtFloat *result, ...);

RtInt RxTexturePoints1(RtString filename, RtIntnPoints, RtInt firstchannel, RtInt nchannels,
                       RtFloat *s, RtFloat *t, RtFloat *result, ...);

DSOs may perform filtered texture map lookups using four point versions of the corresponding shading language shadeops. Each function takes a string specifying a texture filename, four points specifying the region to be textured, and an optional parameter list. nchannels of texture data are retrieved starting at firstchannel, and stored in result. There are also corresponding vector versions (RxTextureV and so on) that take arrays of token value pairs in the same manner as other Ri calls.

For the multi-point versions of each function, the data pointers for input and results should be interleaved. For example, P0 in RxShadowPoints should point to a sequence of nPoints elements, each of which is an RtPoint.

The multi-point versions can also take a RI_RUNFLAGS parameter that can be used to specify which points are active and inactive.

RxTexturePoints1 corresponds to the single-point version of the texture shadeop, filtering the texture map lookup using the smooth derivatives. If smooth derivatives are not available, it reverts to using the four-point call with the provided s and t used for all four points.

  • Important

    RxTexture has been deprecated in favor of RxTexturePoints. RxTexture will, for now, continue to work, but incurs a significant performance penalty. We cannot overstate how much users are encouraged to use RxTexturePoints instead.

A trivial example follows. The following DSO shadeop performs a 3 channel texture lookup.

#include "RslPlugin.h"
#include "rx.h"

extern "C" {

RSLEXPORT int rxtexture(RslContext* rslContext,
                        int argc, const RslArg* argv[])
{
    RslStringIter texturename(argv[1]);

    float* s0; int s0_stride; argv[2]->GetData(&s0, &s0_stride);
    float* s1; int s1_stride; argv[3]->GetData(&s1, &s1_stride);
    float* s2; int s2_stride; argv[4]->GetData(&s2, &s2_stride);
    float* s3; int s3_stride; argv[5]->GetData(&s3, &s3_stride);

    float* t0; int t0_stride; argv[6]->GetData(&t0, &t0_stride);
    float* t1; int t1_stride; argv[7]->GetData(&t1, &t1_stride);
    float* t2; int t2_stride; argv[8]->GetData(&t2, &t2_stride);
    float* t3; int t3_stride; argv[9]->GetData(&t3, &t3_stride);

    float* result; int result_stride; argv[0]->GetData(&result, &result_stride);

    unsigned int numPoints;
    const RslRunFlag* runFlags = rslContext->GetRunFlags(&numPoints);

    RtInt status;

    status = RxTexturePoints4(*texturename, numPoints, 0, 3, s0, s1, s2, s3,
                               t0, t1, t2, t3, result, RI_RUNFLAGS, runFlags, NULL);

    return status;

}
static RslFunction myFunctions[] =
{
    { "color rxtexture (string, float, float, float, float, float, float, float, float)", rxtexture },
    NULL
};
RSLEXPORT RslFunctionTable RslPublicFunctions = myFunctions;

} // extern "C"

The resulting DSO shadeop can be invoked as follows:

surface rxtexture (string txname="")
{
    if (txname != "") {
    Ci = rxtexture(txname, s, t, s, t, s, t, s, t);
    }
    Oi = 1;
}
  • Important

    Parameters passed to RxTexture must match type and detail. The requirements for each parameter are listed here.


3D Texture Write and Lookup

RtInt RxBake3d(RtString filename, RtPoint point, RtNormal normal, RtFloat radius, ...);

RtInt RxTexture3d(RtString filename, RtPoint point, RtNormal normal, RtFloat filterradius, ...);

RxBake3d writes data points to a point cloud file. RxTexture3d reads texture data from a point cloud, brick map, or deep shadowmap file. There are also corresponding vector versions (RxBake3dV, etc.) that take arrays of token value pairs in the same manner as other Ri calls.

Here's a simple example of a DSO shadeop that uses RxTexture3d() to look up a color in a brick map file:

#include <stdio.h>
#include "RslPlugin.h"
#include "rx.h"

RSLEXPORT int dsotexture3d(RslContext* rslContext,
                           int argc, const RslArg* argv[])
{
    RslStringIter bkmfilename(argv[1]);
    RslPointIter p(argv[2]);
    RslNormalIter n(argv[3]);
    RslFloatIter r(argv[4]);
    float c[3];

    for (int i=0; i < argv[2]->NumValues(); i++) {
        RxTexture3d(*bkmfilename, *p, *n, *r, "color c", *c, NULL);
        printf("color c = (%f %f %f)\n", c[0], c[1], c[2]);
        ++p; ++n; ++r;
    }

    return 0;
}
static RslFunction myFunctions[] =
{
    { "float dsotexture3d (string, point, normal, float)", dsotexture3d },
    NULL
};
RSLEXPORT RslFunctionTable RslPublicFunctions = myFunctions;

} // extern "C"

Optional parameters such as "lerp" or "maxdepth" must be passed to RxTexture3d() using the rather quaint syntax '&*'. For example:

RxTexture3d(*bkmfilename, *p, *n, *r, "color c", *c, "lerp", &*lerp, NULL);

If you want to look up more than one variable with RxTexture3d(), just list the variable names and variables after each other. For example, to look up a color c and a float f, the RxTexture3d() call looks like this:

RxTexture3d(bkmfilename, p, n, r, "color c", c, "float f", f, NULL);

Attribute And Option State

int RxAttribute (const char *name, void *result,
                 int resultlen, RxInfoType_t *resulttype, int *resultcount);

int RxOption (const char *name, void *result, int resultlen,
              RxInfoType_t *resulttype, int *resultcount);

These calls duplicate the functionality of the attribute() and option() shadeop, allowing the DSO to determine information about the current graphics state by looking up the data associated with a token-data pair in an Attribute or Option.

The name of the option or attribute to look up is passed in via name; the names that are supported include all the ones supported by the corresponding shadeop, as well as user specified attributes and options specified using the syntax user:nameofattribute.

Note that some options and attributes are set using values of type RtInt; when queried with RxAttribute or RxOption, however, they will return values of type RtFloat, and a resulttype of RxInfoFloat, as when queried by the attribute() or option() shadeops. However, if an attribute or option is of type RtInt and is a user attribute/option, it will be correctly returned as an int with a resulttype of RxInfoInt.

Return values are stored in result, which should be a pointer to a contiguous chunk of memory allocated by the DSO, with size in bytes equal to resultlen. PRMan will attempt to store the results of the option or attribute call inside the storage after checking resultlen. On return, resulttype and resultcount indicate the type of data and number of items returned inside result. If the storage is not large enough to store the requested attribute or option value, the Rx call will fail with nonzero status and set the resultcount to the required size. If name is an invalid option or attribute, then the Rx call will fail with a nonzero status and set resultcount to zero. Checking resulttype and resultcount is particularly important for user defined attributes or options, where the type of the data may not be as expected, due to unknown RiDeclare declarations.

Note that special care must be taken when querying an attribute or option that has a value of type string. In this case, result must be a pointer to a string (char**), and the size of the string pointer (sizeof(char*)) must be passed in via resultlen. On return, *result contains the value of the string; this allocation is owned by the renderer and must not be freed.

A usage example follows. The following DSO shadeop returns a color when given a named attribute also of type color, and may be invoked by a shader using rxgetattrcolor("nameofattribute");

#include "RslPlugin.h"
#include "rx.h"

RSLEXPORT int rxgetattrcolor(RslContext* rslContext,
                             int argc, const RslArg* argv[])
{
    RslColorIter out(argv[0]);
    RslStringIter name(argv[1]);
    RxInfoType_t type;
    float tmp[3];
    int count;
    int status = RxAttribute(*name, tmp, sizeof(RtColor),
                 &type, &count);
    if (status != 0 || type != RxInfoColor && count != 3) {
        /* The attribute did not exist - set the color to black */
        tmp[0] = tmp[1] = tmp[2] = 0.0f;
    }

    // The result color might be varying and need multiple values
    for (int i=0; i < argv[0]->NumValues(); i++) {
        (*out)[0] = tmp[0];
        (*out)[1] = tmp[1];
        (*out)[2] = tmp[2];
        ++out;
    }

    return status;
}
static RslFunction myFunctions[] =
{
    { "color rxgetattrcolor(string)", rxgetattrcolor },
    NULL
};
RSLEXPORT RslFunctionTable RslPublicFunctions = myFunctions;

}; // extern "C"

PRMan 17 introduced a new Rx call: RxAttrIdNameStack.

int RxAttrIdNameStack(const char *idstack[], unsigned maxlen);

RxAttrIdNameStack returns a list of names representing the attribute scopes enclosing the current Ri stream position. The caller provides memory into which the renderer writes the name at each level. A positive returncode represents success and will be less than the provided maximum length. idstack[0] is the innermost scope. idstack[returnval-1] is the outtermost scope. Nonpositive return codes represent failure, the magnitude of the result represents the size of the memory block needed to store a result. A Return value of 0 indicates other exceptional (error) conditions.


Renderer Information

int RxRendererInfo (const char *name, void *result, int resultlen,
                    RxInfoType_t *resulttype, int *resultcount);

This call duplicates the functionality of the rendererinfo() shadeop, allowing the DSO to determine which renderer and which version it is currently running in. Much like the RxAttribute and RxOption calls described above, return values are stored in a contiguous memory block result of size resultlen, with resulttype and resultcount indicating the type of data and number of items returned. The following may be passed in as the value for name:

renderer

result needs to be large enough to hold a pointer to a string (resultlen should be equal to sizeof(char*)). On return, *result contains a string containing the name of the renderer. This allocation is owned by the renderer and must not be freed. Example usage:

char *renderer;
    status = RxRendererInfo("renderer", &renderer, sizeof(char*),
                            &type, &count);
version

result must be large enough to hold an array of four int (resultlen should be 4 * sizeof(int)). On return, result contains the version of the renderer. Example usage:

int version[4];
    status = RxRendererInfo("version", &version, 4 * sizeof(int),
                            &type, &count);
versionstring

result needs to be large enough to hold a pointer to a string (resultlen should be equal to sizeof(char*)). On return, *result contains a string containing the version of the renderer as a string. This allocation is owned by the renderer and must not be freed. Example usage:

char* versionstring;
    status = RxRendererInfo("versionstring", &versionstring, sizeof(char*),
                            &type, &count);

Texture Information

int RxTextureInfo(const char *filename, const char *querystring,
                  void *result, int resultlen, RxInfoType_t *resulttype,
                  int* resultcount);

This call duplicates the functionality of the textureinfo() shadeop.


Transformations

RtInt RxTransform (RtToken fromspace, RtToken tospace,
                   RtFloat time, RtMatrix m);
RtInt RxTransformPoints (RtToken fromspace, RtToken tospace,
                         RtInt n, RtPoint p[], RtFloat time);

RxTransform calculates at shutter-normalized time time the transformation from the space given by fromspace to the space given by tospace and stores the result in the matrix m.

RxTransformPoints transforms the points in the array p from the space given by fromspace to the space given by tospace. The parameter n is the number of points in the array and time is the shutter-normalized time at which the transformation is evaluated.

Both functions return 0 if successful, -1 if one of the named spaces was not found, or -2 if the given transform was not computable due to a singular matrix.