Prev | Next



Rx API

July, 2009

images/note_important.gif

* The Rx API will soon be deprecated in favor of Rix.

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.

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.

images/note_important.gif

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[])
{
    RslColorIter result(argv[0]);
    RslStringIter texturename(argv[1]);
    RslFloatIter s0(argv[2]); RslFloatIter s1(argv[3]); RslFloatIter s2(argv[4]); RslFloatIter s3(argv[5]);
    RslFloatIter t0(argv[6]); RslFloatIter t1(argv[7]); RslFloatIter t2(argv[8]); RslFloatIter t3(argv[9]);
    int numPnts = argv[0]->NumValues();
    int status;

    status = RxTexturePoints4 (*texturename, numPnts, 0, 3, &(*s0), &(*s1),
                              &(*s2), &(*s3), &(*t0), &(*t1), &(*t2), &(*t3), *result, 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;
}
images/note_important.gif

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 brick map 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.

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"

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.


Prev | Next


Pixar Animation Studios
Copyright© Pixar. All rights reserved.
Pixar® and RenderMan® are registered trademarks of Pixar.
All other trademarks are the properties of their respective holders.