Querying Variables of a Material Program

So I am in the process of writing a path tracing application that uses OptiX at its core. I want to create a UI which can set the properties of a material program on the fly. For example a simple diffuse material could have a variable “color” which is set cpu side. However I would like the application to be quite open such that a user could write their own material programs and the UI will add controls relative to any input variables that the material program may have. So my question is, Is there a way to query an optix material program of the input variables it may have?


I’ve done similar things using opengl shaders. It is easier, as the shaders are much easier to parse, and don’t go through a compile step before being loaded in. In optix, we go .cu -> .ptx via compiler, before we load them in.

I’ve played around with parsing the compiled ptx files for this information. When I load a program, I generate a table of variables, type, etc… and use some conventions to make it all possible.

You will find lines like:

.global .align 4 .u32 globalRenderFlags;

You can then just call rtContextDeclareVariable with the “globalRenderFlags” for example in order to bind to it and then be able to set it.

Of course, you will want to use some conventions to determine what sort of ui widgets you use for the different possible variables. ex// specular_color, you use the color as a signal to have a widget for editing HSV, or whatever.


Something else I wanted to look into, was reloading / recreating material programs and linking them back up to the rest of the scene. I’ve done this in GL engines, that allowed me to edit shaders on the fly, then just hit a reload button. I’m wondering if something like this would be possible with optix, of course requiring the use of the nv compiler.

ex// load new material, call rtGeometryInstanceSetMaterial to reset it, then delete old one.

Just some thoughts incase anyone has played with doing this. Makes iterating on programs quick.

On the variable query, there is nothing in OptiX like the query for active shader variable names and types like in GLSL.
You can only iterate over the variable count with the rtGetVariableCount and rtGetVariable functions or query by variable name if you know the name.
We had been parsing the PTX code as well on our scene graph.

Today I’m loading material parameters and their default values for my path tracer from text based descriptions, like XML or an own format.
If a user can implement own shaders you could also let him provide that interface description.

Reloading materials on the fly is also possible. OptiX needs to recompile the kernel for that each time.
But to be able to compile the CUDA code you’d requires a full development environment for the host compiler.
Having an application running, developing the shader inside the Visual Studio IDE, compiling it to PTX with nvcc, and then pressing a button in the running app to reload the new PTX is basically the fastest and least error prone you could get.

Everything else would require that you meticulously handle every error you have during interactive development or OptiX will answer with exceptions. nvcc is also not the fastest, so I doubt interactive compilation of shaders during typing is a lot of fun.

RTresult RTAPI rtVariableGetAnnotation(RTvariable v, const char** annotation_return);

This is also usefull for pulling an user annotation, I believe, that could store things such as what sort of ui widget to edit the param with, or how the engine should update / handle it.

Yes, that is normally used to transfer additional user information like needed for automatic GUI building. We’ve used this in our scene graph’s COLLADA profile_COMMON OptiX shader implementation, e.g. for things like this (and even for a ListBox driving a bitfield, not shown here)

rtDeclareVariable( float4, reflective, , string UIWidget = "ColorPicker"; );

rtDeclareVariable( float, reflectivity, , 
                   string UIWidget = "Slider"; 
                   float UIMin = 0.0;
                   float UIMax = 1.0;
                   float UIStep = 0.01; );

But unfortunately there really is no call to get the variable names of active variables. Probably complicated by the fact that there is a variable scope hierarchy at each variable declaration level.
You could of course add that as annotation as well.