FNNDSC / ami

AMI Medical Imaging (AMI) JS ToolKit
https://fnndsc.github.io/ami/#viewers_upload
MIT License
717 stars 213 forks source link

[feature] Support 2D transfer functions #216

Open cancan101 opened 6 years ago

cancan101 commented 6 years ago

Pepost from here.

Support 2D transfer functions, leveraging gradient information to improve visualization. e.g. to determine coloring and opacity based on pixel scalar intensity and / or gradient magnitude. This may be a separable 1d transfer Functions or a 2d transfer function.

In addition to VTK, ImageVis3D also supports this.

NicolasRannou commented 6 years ago

That is a good one - are you planning to look into it? We may (was long time ago) already have some gradient information available in the shaders here

Right now the gradient is only updated when trilinear interolation is ON: trilinear interpolation

@daron1337 may have some advices as it is required for the shading -

cancan101 commented 6 years ago

I'm not sure my bandwidth so I can't commit. That being said would be helpful to start collecting info on this ticket as to what implementation would look like. Right now are 1d transfer Functions supported / is there an example of plugging them in? That would seem like a good start for defining api etc.

daron1337 commented 6 years ago

@NicolasRannou for the phong shading uInterpolation is set to 1 thus trilinear is ON. As you said I use it in the phong for the light reflection.

NicolasRannou commented 6 years ago

AMI used to support transfer functions, that was lost at some point in favor of direct texture color/opacity lookup but definitely something I'd love to see back in -

Ideally we may need 3 transfer functions to be passed to the shaders: color, opacity and gradients, correct?

Each transfer function could be represented in the shaders as a pair of 2 arrays:

For instance, the Color TF related arrays could be: [color1, color2, color3] [value1, value2, value3]

Then in the shaders, for each voxel value we can retrieve color, opacity. (some interpolation may be needed)

I'm most worried about performance but that may be irrelevant?

cancan101 commented 6 years ago

The way I have seen the function represented in the past is as a vector function: 2d: f(x, grad(x)) -> (R,G,B,A) or 1d: f(x) -> (R,G,B,A).

I assume that the function can be applied to all voxels up front so avoid having to recalculate on each render.

cancan101 commented 6 years ago

So I think most of the code is in place. The idea would be to pre-create a 2D texture by evaluating the 2D transfer function at all points in the (x, grad(x)) space and then sample from that texture within the shader. I think this would be changed to use the grad when sampling assuming uLut==2. Most of the work is just evaluating the transfer function at all points in the grid.

NicolasRannou commented 6 years ago

Yes that makes sense to me!