RenderKit / ospray

An Open, Scalable, Portable, Ray Tracing Based Rendering Engine for High-Fidelity Visualization
http://ospray.org
Apache License 2.0
1.01k stars 182 forks source link

Extending the available information within a Model and access it on hit #466

Closed NadirRoGue closed 3 years ago

NadirRoGue commented 3 years ago

Hello everyone,

We are currently using OSPRay to render geometric models with simulation. (we are using 1.8.5, update to a more recent version is planned, but for the time being we have to use this version).

Each geometry has been extended to include an index for an array that contains the simulation data. The renderer object has been also extended to hold the simulation data array, as well as a transfer function that we use to compute a color from the simulation data value.

This allow us to support only one model simulation at a time, since there is only 1 buffer.

We now need to support multiple model simulations within the same scene. To achieve that, the approach taken has been to extend the Model struct, and add to it the simulation array and a transfer function object, in such way that when we hit something, we can reach the model through the DifferentialGeometry -> Geometry -> Model

struct CustomModel
{
    Model super;

    // Transfer function attributes
    const uniform TransferFunction* uniform transferFunction;

    // Simulation data
    uniform float* uniform simulationData;
    uint64 simulationDataSize;

    // Secondary model
    uniform CustomModel* uniform secondaryModel;
    float maxDistanceToSecondaryModel;
};

However, we are unable to call the transfer function object methods, because its type when accessed through the DifferentialGeometry is const uniform TransferFunction* varying, and it results in a compile error because the function expects an uniform TransferFunction* uniform object.

I am not sure if this is the best approach for what we are trying to achieve (nor is my ISPC knowledge great), but is there any way to circumventing this issue? Or perhaps a better approach?

Kind regards.

timsandstrom commented 3 years ago

I was waiting for the OSPRay folks to chime in and you've probably resolved this already. I'm no expert in ispc, but I think some fields benefit by being const, for optimization. The example in VolumetricModel.ispc does not use const for the transfer function pointer. I've done something similar for Mesh's but will try to add that to GeometricModel, this would allow spheres, hair, and other primitives to be 'scalar mapped' using a transfer function. something like:

GeometricModel_postIntersect(...) { // I 'piggyback' on the DG_COLOR flag, but test against my added 'scalar' field if (flags & DG_COLOR && valid(self->scalar)) { dg.color = self->transferFunction->get(...) } ... }

carsonbrownlee commented 3 years ago

hi Nadir, sorry for the late reply. In general we would recommend that data operations take place outside of OSPRay and see if you can map what you are doing through OSPRay's existing representation. If it does make more sense to modify OSPRay directly, then unfortunately you will need to get up to speed on ISPC programming, and understanding control flow across gangs is generally the trickiest part. The best resource is the ISPC User guide, in particular the sections on uniform vs varying control flow: https://ispc.github.io/ispc.html.

johguenther commented 3 years ago

Apologies from my side as well for the late reply. To call functions on an object that can be varying (in your case the CustomModel, which can be different for neighboring pixels that are computed together) the typical way is to use foreach_unique. See here for an example: https://github.com/ospray/ospray/blob/master/ospray/render/pathtracer/PathSampler.ispc#L59-L61

johguenther commented 3 years ago

Please reopen if you have further questions.