Graphics Reference
In-Depth Information
Expanding everything gives
color * = α 0 * color 0 + (1 − α 0 ) α 1 * color 1 + (1 − α 0 )(1 − α 1 ) α 2
* color 2 + (1 − α 0 )(1 − α 1 ) (1 − α 2 )black.
There's a patern here, so let's look at how this appears when we move
front-to-back. The fragment shader keeps a running alpha value called α * ( astar
in the code below) and a running RGB color value called color * ( cstar ). The
variable α * is the transparency factor that the next voxel's contribution will be
multiplied by, and color * is the combined color so far. These get updated with
every step taken. The final value of color * is then displayed at that fragment.
Why do it front-to-back when back-to-front seems more intuitive? The
reason is that we can usually obtain significant time savings this way. If α * ever
becomes 0., this means that the arrow has encountered a completely opaque
voxel and, thus, no data beyond that point will count toward the final color,
so the code can safely break out of the loop. This may not sound like much,
but over the course of thousands of fragments and hundreds of steps at each
fragment, it can really add up!
const float SMIN = 0.;
const float SMAX = 120.;
uniform float uMin;
uniform float uMax;
uniform sampler3D uTexUnit;
uniform float uTol;
uniform int uNumSteps;
uniform float uAmax;
in vec3 vSTP0; // starting texture location
in vec3 vDirSTP; // tracing step
out vec4 fFragColor;
void main( )
{
float astar = 1.;
vec3 cstar = vec3( 0., 0., 0. );
vec3 STP = vSTP0;
for( int i = 0; i < uNumSteps; i++, STP += vDirSTP )
{
// keep looping if we're out of bounds:
if( any( lessThan( STP, vec3(0.,0.,0.) ) ) )
Search WWH ::




Custom Search