3
$\begingroup$

In the OSL spec, there is a an optional parameter in a trace call for a 'traceset'.

I would like to restrict a trace to only hit the same object. The solution I have right now is to get the object name and test the trace object name after it hits like this:

// start OSL code fragment
string thisobjname = "";
getattribute("geom:name",thisobjname);
int hit = trace(P, 
           ((_var_42 - 0.5) * 2.0), 
           );
string hitobjname = "";
getmessage("trace","geom:name",hitobjname);
if( hit && hitobjname==thisobjname)
           printf("trace hit the same object");
// end OSL code fragment

I tried the following, but it does not work.

// start OSL code fragment
string thisobjname = "";
getattribute("geom:name",thisobjname);
int hit = trace(P, 
           ((_var_42 - 0.5) * 2.0), 
           "traceset", thisobjname
           );
string hitobjname = "";
getmessage("trace","geom:name",hitobjname);
if( hit)
           printf("trace hit the same object");
// end OSL code fragment

How does the 'traceset' need to be formatted to work? Is there something else wrong?

$\endgroup$
0

1 Answer 1

2
$\begingroup$

I have traced this back to the OSL code where the 'traceset' is accepted and passed out to the compiled 'oso' file. This is further passed to Cycles to be executed and does indeed include the 'traceset' string.

However, on picking through the Cycles source code I came across the only reference to 'traceset' in the following function (trace) :

bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
    const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
    const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
    const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy)
{
    /* todo: options.shader support, maybe options.traceset */
    ShaderData *sd = (ShaderData *)(sg->renderstate);

    /* setup ray */
    Ray ray;

    ray.P = TO_FLOAT3(P);
    ray.D = TO_FLOAT3(R);
    ray.t = (options.maxdist == 1.0e30f)? FLT_MAX: options.maxdist - options.mindist;
    ray.time = sd->time;

    if(options.mindist == 0.0f) {
        /* avoid self-intersections */
        if(ray.P == sd->P) {
            bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
            ray.P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng);
        }
    }
    else {
        /* offset for minimum distance */
        ray.P += options.mindist*ray.D;
    }

    /* ray differentials */
    ray.dP.dx = TO_FLOAT3(dPdx);
    ray.dP.dy = TO_FLOAT3(dPdy);
    ray.dD.dx = TO_FLOAT3(dRdx);
    ray.dD.dy = TO_FLOAT3(dRdy);

    /* allocate trace data */
    OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
    tracedata->ray = ray;
    tracedata->setup = false;
    tracedata->init = true;
    tracedata->sd.osl_globals = sd->osl_globals;

    /* raytrace */
    return scene_intersect(sd->osl_globals, ray, PATH_RAY_ALL_VISIBILITY, &tracedata->isect, NULL, 0.0f, 0.0f);
}

Note the comment /* todo: options.shader support, maybe options.traceset */ - this is the only mention in Cycles source of 'traceset'. So, although the 'traceset' is passed into Cycles from the OSL shader it is not actually processed. This would seem to show that the 'traceset' option of the OSL 'trace' call has not yet been implemented.

$\endgroup$
3
  • $\begingroup$ This is great investigation! Which version of the Blender was this source code from? $\endgroup$
    – Ed Tate
    Commented Apr 21, 2018 at 14:44
  • $\begingroup$ Thanks @EdTate. It was the latest Cycles and latest OSL so, presumably, all Blender versions. $\endgroup$ Commented Apr 21, 2018 at 14:53
  • 1
    $\begingroup$ still seems to be true, checked master branch in blender's official github mirror, the todo comment is still there and is still the only mention of traceset) $\endgroup$
    – amgg
    Commented Nov 10, 2021 at 22:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .