This example performs naive line integral convolution (LIC) in a 2D flow field. The contrast of the result is modulated by the flow magnitude (lower contrast at lower velocity), and the coloring is according to the flow vorticity.
For demonstration purposes, some variables and inputs for this program
are specific to a particular flow field (../data/sqflow2D.nrrd
),
which we symlink to with flow.nrrd
.
First we need the noise texture that will be convolved by streamlines
along the flow. This generates rand.nrrd
:
ln -s ../data/sqflow2D.nrrd flow.nrrd
unu slice -i flow.nrrd -a 0 -p 0 | # get a scalar image
unu resample -s x4.167 x3.125 | # upsample to ~isotropic image
unu 1op nrand -s 42 -o rand.nrrd # randomize with seed 42
The values generated by upsampling are irrelevant; the point of the upsampling is just to create a new grid that lives in the same world-space location as the flow data. Different random values would be generated by different random seeds.
Then we need a colormap for the vorticity; this generates cmap.nrrd
.
echo "0 1 0 1 1 1 1 0 1" |
unu reshape -s 3 3 |
unu resample -s = 300 -k tent -c node | # now a 3x300 array
unu 2op pow - 1.5 | # brighten a bit
unu axinfo -a 0 -k rgb | # its an array of colors
unu axinfo -a 1 -mm -1 1 | # covers [-1,1]
unu dnorm -i - -o cmap.nrrd
With these files in place, we can compile and run lic.diderot
:
diderotc --exec lic.diderot
./lic
The output rgb.nrrd
needs some post-processing because the results
of LIC on the upstream and down-stream halves of the streamline, which
were computed by separate strands, need to be combined (by averaging).
Looking at the initially
statement at the very end, the two halves
are indexed last, so they are the fastest axis of the per-strand
output grid. The output array, however, contains RGB values on the
fastest axis, so it is along axis 1 (length 2) that the averaging of
the results of each half are done, followed by quantizing to an 8-bit
image:
unu project -i rgb.nrrd -a 1 -m mean |
unu quantize -b 8 -min 0 -max 1 -o lic.png
The assertion of quantization range [0,1] is based on the smarts used within the program to anticipate what the contrast of the output will be, based on the assumption of each streamline sampling normally-distributed noise. We can use oversampling to anti-alias (but in this case it comes at 9 times the computational cost):
OVSMP=3
./lic -ovsmp $OVSMP
unu project -i rgb.nrrd -a 1 -m mean |
unu resample -s = /$OVSMP /$OVSMP |
unu quantize -b 8 -min 0 -max 1 -o lic-$OVSMP.png