[vtk-developers] How to emulate the SetCompositeMethodToClassifyFirst behaviour in hardware (vtkOpenGLGPUVolumeRayCastMapper)...

Tjf (mobile) tfogal at sci.utah.edu
Mon Dec 27 15:42:29 EST 2010


Why would you perform trilinear interpolation manually?

All you have to do is set two new uniforms -- let's say 'low' and 'high' -- and use gl_nearest interpolation.  Then you can:

   If(texture3d(vol) < low) { discard; }

and likewise for high, in your fragment shader.  That's going to be much faster.

-tom

Am Dec 27, 2010 um 3:19 AM schrieb AGPX <agpxnet at yahoo.it>:

> Hello everybody,
> 
> I need to render a volume (of scalar values)  that have some regions fully transparent. To avoid the problem that arise from trilinear interpolation of the scalars (that show wrong boundary scalars), I have to use the software volume rendering mapper (vtkVolumeRayCastMapper) where you can customize the composite function. In more details, you can invoke the very useful method SetCompositeMethodToClassifyFirst() of the vtkVolumeRayCastCompositeFunction to obtain the correct result. Unfortunately the software version is slow compared to the hardware one (vtkOpenGLGPUVolumeRayCastMapper). So I have extended the hardware version, rewriting a GLSL shader (starting from vtkGPUVolumeRayCastMapper_CompositeFS.glsl) in order to emulate the behaviour of the vtkVolumeRayCastMapper when you invoke the SetCompositeMethodToClassifyFirst() method. The shader is the following (vtkGPUVolumeRayCastMapper_CompositeFS2.glsl) and you have to add it to the vtkOpenGLGPUVolumeRayCastMapper class:
> 
> /*=========================================================================
> 
>   Program:   Visualization Toolkit
>   Module:    vtkGPUVolumeRayCastMapper_CompositeFS2.glsl
> 
>   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
>   All rights reserved.
>   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
> 
>      This software is distributed WITHOUT ANY WARRANTY; without even
>      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
>      PURPOSE.  See the above copyright notice for more information.
> 
> =========================================================================*/
> 
> // Fragment program part with ray cast and composite method.
> 
> #version 110
> 
> uniform sampler3D dataSetTexture;
> uniform sampler1D opacityTexture;
> 
> uniform vec3 lowBounds;
> uniform vec3 highBounds;
> uniform int textureWidth;
> uniform int textureHeight;
> uniform int textureDepth;
> 
> // Entry position (global scope)
> vec3 pos;
> // Incremental vector in texture space (global scope)
> vec3 rayDir;
> 
> float tMax;
> 
> // from cropping vs no cropping
> vec4 initialColor();
> 
> // from 1 vs 4 component shader.
> float scalarFromValue(vec4 value);
> vec4 colorFromValue(vec4 value);
> 
> // from noshade vs shade.
> void initShade();
> vec4 shade(vec4 value);
> 
> void trace(void)
> {
>   vec4 destColor=initialColor();
>   float remainOpacity=1.0-destColor.a;
> 
>   bool inside=true;
>   
>   vec3 color;
>   vec4 opacity;
> 
>   initShade();
>   
>   float t=0.0;
>   
>   // We NEED two nested while loops. It is trick to work around hardware
>   // limitation about the maximum number of loops.
> 
>   vec3 textureSize = vec3(textureWidth, textureHeight, textureDepth);
>   vec3 texelSize = vec3(1.0, 1.0, 1.0) / textureSize;
>   while(inside)
>     {  
>     while(inside)
>       {
>       vec3 texelpos=textureSize*pos;
>       vec3 lerps = fract(texelpos);
>       vec4 sourcevals[8]; 
>       sourcevals[0] = texture3D(dataSetTexture, pos + vec3(0,           0,           0));
>       sourcevals[1] = texture3D(dataSetTexture, pos + vec3(texelSize.x, 0,           0));
>       sourcevals[2] = texture3D(dataSetTexture, pos + vec3(0,           texelSize.y, 0));
>       sourcevals[3] = texture3D(dataSetTexture, pos + vec3(texelSize.x, texelSize.y, 0));
>       sourcevals[4] = texture3D(dataSetTexture, pos + vec3(0,           0,           texelSize.z));
>       sourcevals[5] = texture3D(dataSetTexture, pos + vec3(texelSize.x, 0,           texelSize.z));
>       sourcevals[6] = texture3D(dataSetTexture, pos + vec3(0,           texelSize.y, texelSize.z));
>       sourcevals[7] = texture3D(dataSetTexture, pos + vec3(texelSize.x, texelSize.y, texelSize.z));
>       vec3 m = vec3(1, 1, 1) - lerps;
>       float weights[8];
>       weights[0] = m.x * m.y * m.z;
>       weights[1] = lerps.x * m.y * m.z;
>       weights[2] = m.x * lerps.y * m.z;
>       weights[3] = lerps.x * lerps.y * m.z;
>       weights[4] = m.x * m.y * lerps.z;
>       weights[5] = lerps.x * m.y * lerps.z;
>       weights[6] = m.x * lerps.y * lerps.z;
>       weights[7] = lerps.x * lerps.y * lerps.z;
>       float weight, totalOpacity;
>       totalOpacity  = weight = texture1D(opacityTexture,scalarFromValue(sourcevals[0])).a*weights[0];
>       color  = shade(sourcevals[0]).xyz*weight;
>       totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[1])).a*weights[1];
>       color += shade(sourcevals[1]).xyz*weight;
>       totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[2])).a*weights[2];
>       color += shade(sourcevals[2]).xyz*weight;
>       totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[3])).a*weights[3];
>       color += shade(sourcevals[3]).xyz*weight;
>       totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[4])).a*weights[4];
>       color += shade(sourcevals[4]).xyz*weight;
>       totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[5])).a*weights[5];
>       color += shade(sourcevals[5]).xyz*weight;
>       totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[6])).a*weights[6];
>       color += shade(sourcevals[6]).xyz*weight;
>       totalOpacity += weight = texture1D(opacityTexture,scalarFromValue(sourcevals[7])).a*weights[7];
>       color += shade(sourcevals[7]).xyz*weight;
>       destColor.xyz += remainOpacity*color;
>       remainOpacity *= (1.0 - totalOpacity);
>       pos=pos+rayDir;
>       t+=1.0;
>       inside=t<tMax && all(greaterThanEqual(pos,lowBounds))
>         && all(lessThanEqual(pos,highBounds))
>         && (remainOpacity>=0.0039); // 1/255=0.0039
>       }
>     }
>   gl_FragColor = destColor;
>   gl_FragColor.a = 1.0-remainOpacity;
> }
> ;
> 
> The algorithm performs trilinear interpolation manually so you have to call SetInterpolationTypeToNearest() when you use this shader. In addition you have 3 new uniform variables:
> 
> uniform int textureWidth;
> uniform int textureHeight;
> uniform int textureDepth;
> 
> that maintains the dimensions of the 3D texture. You have to modify the class vtkOpenGLGPUVolumeRayCastMapper to provide these additional informations to the shader.
> 
> I hope that this could be helpful for other guys and that (one day) this feature will be added to the VTK library :)
> 
> Bye,
> 
> Gianluca Arcidiacono (AGPX)
> 
> 
> 
> _______________________________________________
> Powered by www.kitware.com
> 
> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
> 
> Follow this link to subscribe/unsubscribe:
> http://www.vtk.org/mailman/listinfo/vtk-developers
> 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtk-developers/attachments/20101227/50c3e4fe/attachment.html>


More information about the vtk-developers mailing list