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 which 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.
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.
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 floats in, 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.
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 RxTexturePoints(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, ...);
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.
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 = RxTexturePoints (*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; }
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);
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.
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; if the storage is not large enough to store the requested attribute or option value, the Rx call will fail with nonzero status. On return, resulttype and resultcount indicate the type of data and number of items returned inside result. 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 which 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"
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, 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:
char *renderer; status = RxRendererInfo("renderer", &renderer, sizeof(char*), &type, &count);
int version[4]; status = RxRendererInfo("version", &version, 4 * sizeof(int), &type, &count);
char* versionstring; status = RxRendererInfo("versionstring", &versionstring, sizeof(char*), &type, &count);
Pixar Animation Studios
|