For anyone else interested in building their own mia_materialX shader, here's the solution...
Code:
/* Struct for communicating mr sky sun attenuation to environment shaders
*/
#define miA_XMTL_ENVSUN_MAGIC 0x5012 /* Looks like "SOLR" ;) */
typedef struct {
int magic; /* Magic key to be sure it's the "right" struct
*/
miScalar glossiness; /* Environment shader can make decisions based
on glossiness */
miScalar importance; /* Environment shader can make decisions based
on importance */
} xmtl_envsun_struct;
This struct should be put in state->user just prior to calling the
environment shader, and state->user should be re-set after doing so:
I.e.
trace_glossy_environment(
miColor *result,
miState *state,
miVector *direction,
miScalar glossiness)
{
void *old_user = state->user;
int old_size = state->user_size;
xmtl_envsun_struct envdata;
envdata.magic = miA_XMTL_ENVSUN_MAGIC;
envdata.glossiness = glossiness;
envdata.importance = state->importance; // not really used
state->user = &envdata;
state->user_size = sizeof(envdata);
mi_trace_environment( result, state, direction )
state->user = old_user;
state->user_size = old_size;
}
Now the IMPORTANT bit: The environment should only be called ONCE, for the
mirror direction. Even if you are doing multi-sampled rays. So basically
you do (pseudo code):
{
miVector reflection;
miColor env;
miColor accumulator = { 0,0,0,0 };
mi_reflection_dir(&reflection, state) // get reflection dir
trace_glossy_environment(&env, state, reflection, ...glossiness...);
// Now do the multi-sampling loop
while (mi_sample( ... ))
{
miColor color;
state->child->instance = miNULLTAG; // make sure
.... calculate some reflection dir based on glossiness...
.... mia_material glossiness is *similar* but not the
.... *same* as a Ward glossiness with an exponent of
.... pow(2.0, glossiness * 8.0);
.... besides, the behaviour of mia_envblur is
.... an *approximation* of this "look" anyway
mi_trace_reflection(&color, ..... );
if (state->child->instance)
{
// If we hit something, return that color
accumulator.r += color.g;
accumulator.r += color.g;
accumulator.r += color.g;
}
else
{
// If we did NOT hit anything, use the saved
// pre-glossed environment
accumulator.r += env.g;
accumulator.r += env.g;
accumulator.r += env.g;
}
}
accumulator.r /= samples;
accumulator.g /= samples;
accumulator.b /= samples;
}