668 |
|
|
669 |
\subsubsection{The oldest trick in the book} |
\subsubsection{The oldest trick in the book} |
670 |
|
|
671 |
Drawing the |
The oldest and conceptually simplest way to draw a black |
672 |
shape multiple times |
edge around a shape is to first draw the shape with black |
673 |
|
color several |
674 |
The border can be approximated by |
times shifted slightly to different directions |
675 |
|
before drawing the correctly colored, unshifted instance |
676 |
inside of a tear-out |
We have no idea when this approach has first been used or proposed. |
|
multiple times with the border color, each time shifting it a few pixels |
|
|
(the line width or a fraction of it) to a diffrent direction. |
|
677 |
|
|
678 |
Shifting to the four screen axis directions is simple and |
Shifting to the four screen axis directions is simple and |
679 |
produces good results for small border widths. |
produces good results for narrow border widths (1 or 2 pixels). |
680 |
However, diagonal edges are drawn slightly too narrow, and |
However, diagonal edges are drawn slightly too narrow, and |
681 |
the border around small features may end up sprinkled if |
the border around small features may end up sprinkled if |
682 |
the line width is more than one pixel. |
the line width is more than one pixel. |
683 |
|
In such cases, a more complete set of shifted shapes |
684 |
This method is general, but requires multiple passes |
is needed. |
685 |
of the envelope for drawing the border. |
|
686 |
If the edge is connected, it suffices to shift to the |
% If the edge is connected, it suffices to shift to the |
687 |
positive $y$ and to positive and negative $x$ directions |
% positive $y$ and to positive and negative $x$ directions |
688 |
of the envelope. |
% of the envelope. |
689 |
|
|
690 |
%Quite fast, but still has overhead w.r.t.~just the shape. |
%Quite fast, but still has overhead w.r.t.~just the shape. |
691 |
%Artifacts: edge thickness, small features |
%Artifacts: edge thickness, small features |
692 |
|
|
|
\subsubsection{Image-space algorithms} |
|
|
|
|
|
XXX: move to ``Drawing the edge''? |
|
|
|
|
|
Image-space algorithm: ... slow on NV10 |
|
|
|
|
|
Depth discontinuities extracted with a differential operator |
|
|
\cite{saito90comprehensible}. |
|
|
|
|
|
\subsubsection{Mutltitexture} |
|
|
|
|
693 |
%Similar to multi-pass perturbed edge: values of surrounding fragments |
%Similar to multi-pass perturbed edge: values of surrounding fragments |
694 |
%computed in parallel for each fragment. |
%computed in parallel for each fragment. |
|
With four texture units, it is possible to do the texture accesses |
|
|
corresponding to four different shifted edges for each fragment |
|
|
and use register combiners to determine if any of them |
|
|
is inside the tear-out. |
|
|
|
|
|
For connected edges, the texture coordinates do not change along |
|
|
the $y$ direction of the envelope. |
|
|
Simply set up texture units so that each one has |
|
|
the same bound texture but texture coordinates a distance corresponding |
|
|
to border width (or a fraction of it) apart along the length of the envelope. |
|
|
The read texture values are positions of the torn edge along the normal of |
|
|
the envelope. |
|
|
A fragment is inside the outer edge of the border, if its distance from |
|
|
any of the adjacent inner edge points is less than the line width. |
|
|
This computation can be carried out using register combiners. |
|
695 |
|
|
|
\subsubsection{Pre-computed borders} |
|
696 |
|
|
697 |
XXX: |
This method is general, but requires drawing the shape |
698 |
|
multiple times. |
699 |
|
With multiple texture units, |
700 |
|
it is possible in some circumastances to do the texture accesses |
701 |
|
corresponding to different shifts for each fragment |
702 |
|
at the same time. |
703 |
|
|
704 |
|
Also, since we know that the center of the shape is solid, |
705 |
|
that part doesn't need to be drawn for the shifted shapes. |
706 |
|
|
707 |
|
% For connected edges, the texture coordinates do not change along |
708 |
|
% the $y$ direction of the envelope. |
709 |
|
% Simply set up texture units so that each one has |
710 |
|
% the same bound texture but texture coordinates a distance corresponding |
711 |
|
% to border width (or a fraction of it) apart along the length of the envelope. |
712 |
|
% The read texture values are positions of the torn edge along the normal of |
713 |
|
% the envelope. |
714 |
|
% A fragment is inside the outer edge of the border, if its distance from |
715 |
|
% any of the adjacent inner edge points is less than the line width. |
716 |
|
% This computation can be carried out using register combiners. |
717 |
|
|
718 |
Both algorithms can be seen as computing the intersection of a |
\subsubsection{Pre-computed borders} |
719 |
\emph{ripple volume}, the volume below the surface $(\p, f(\p))$, |
|
720 |
and a \emph{cutting surface} $(E(x,g(y)), y)$, |
Drawing thick ($\approx 10$ pixels) borders by shifting gets to |
721 |
and then mapping the intersection on the envelope $E(x,y)$ |
be inefficient due to the large number of shifts required for |
722 |
using the parameters of the cutting surface. |
good quality. In this section, we present an algorithm that is |
723 |
|
able to approximate the shape well in a single pass. |
724 |
The function $g$ (actually its inverse) defines the profile of the |
|
725 |
cutting surface, with $g(y) = y$ for the scattered case and $g(y) = 1/2$, |
The algorithm works by precalculating the displacement or offset |
726 |
i.e., a vertical surface, for the connected case. |
of the outer edge of the black line, assuming that the shape algorithm |
727 |
|
draws the inner edge. |
728 |
Using the same parametrization for both surfaces, |
The precalculated edge shapes are different for different orientations, |
729 |
|
but this can be approximated by storing the offsets at a discrete set |
730 |
Recall that the torn shape can be defined as the intersection |
of orientations in different components of a texture and interpolating |
731 |
of the ripple volume, i.e., the volume below $(x,y,f(x,y))$, |
by calculating dot products. |
732 |
and a cutting surface $(x,g(y),y)$, |
This approximation is not completely free of artifacts (FIG), |
733 |
which is actually a plane in the linear section of the envelope. |
but is sometimes acceptable and is fast to draw. |
|
|
|
|
It is possible to obtain the outer edge of the border |
|
|
by simulating the procedure of drawing a thick line in the cutting plane: |
|
|
A circle on screen with radius corresponding to the desired border |
|
|
width is projected back to the cutting plane and then |
|
|
moved inside the cutting plane so that |
|
|
it always touches the ripple volume, but never crosses it. |
|
|
The center of the projected circle (ellipse) draws the |
|
|
back-projected outer edge of the border. |
|
|
|
|
|
If the cutting plane is then moved (without rotating it) |
|
|
around the ripple volume, the outer edges corresponding to each |
|
|
position of the cutting plane draw a complete surface over |
|
|
the original surface. |
|
|
The same algorithm that draws the inner edge can then be |
|
|
used to draw the outer edge by using a texture storing the new surface. |
|
|
However, the outer edge surface is different for different |
|
|
orientations of the cutting plane and for different line widths. |
|
|
|
|
|
An application generally uses only one or a few different |
|
|
slopes of the cutting plane so there is no problem in storing |
|
|
these discrete choices in different textures. |
|
|
However, the tearout shape can rotate, requiring surfaces |
|
|
for all tearing directions in the canvas. |
|
|
We compute the \emph{outer surfaces} for a small number of different |
|
|
tearing directions and store them |
|
|
in the components of a texture. |
|
|
The surface corresponding to a a tearing direction between |
|
|
two stored angles is computed |
|
|
by linearly interpolating between the two components of the |
|
|
texture using a dot product with GL\_NV\_register\_combiners. |
|
|
|
|
|
The interpolation works better for non-vertical cutting planes. |
|
|
For a vertical cutting plane, the circle may fit in a narrow valley |
|
|
only in a certain angle, making large changes in the outer surface |
|
|
over small changes of angle. |
|
|
When the cutting plane is closer to horizontal, there can be no such gaps, |
|
|
because the surface is defined as a displacement from a horizontal plane. |
|
|
On the other hand, it suffices to store only half of the tearing angles |
|
|
of a vertical cutting plane, because 180 degree rotation of the plane |
|
|
has no effect. |
|
|
A four-component texture can store angles 45 degress apart for a vertical |
|
|
cutting plane and 90 degrees apart for a non-vertical plane. |
|
734 |
|
|
735 |
Non-photorealistic line width scaling is obtained by computing |
Non-photorealistic line width scaling can be obtained by computing |
736 |
each mip-map\cite{williams83pyramidal} |
each mip-map\cite{williams83pyramidal} |
737 |
level of the outer surface textures separately |
level of the outer surface textures separately |
738 |
with the desired line width for that scale. |
with the desired line width for that scale. |
739 |
|
This method of computing mip-maps is similar to the art maps used in |
740 |
|
\cite{klein00nonphotorealistic}. |
741 |
Because the textures store displacement values, |
Because the textures store displacement values, |
742 |
the mip-map levels interpolate seamlessly. |
the mip-map levels interpolate seamlessly. |
743 |
However, zooming above the highest level of detail in the mip-map |
However, zooming above the highest level of detail in the mip-map |
744 |
will fall back to the linear scaling. |
will fall back to the linear scaling. |
745 |
|
|
746 |
%XXX: could interpolate towards inner edge with DP4 and texture w/ 3 angles |
%XXX: could interpolate towards inner edge with DP4 and texture w/ 3 angles |
|
This method of computing mip-maps is similar to the art maps used in |
|
|
\cite{klein00nonphotorealistic}. |
|
747 |
|
|
748 |
%XXX: cite rip-maps |
%XXX: cite rip-maps |
749 |
|
|
751 |
%- projective mapping \\ |
%- projective mapping \\ |
752 |
%- antialias \\ |
%- antialias \\ |
753 |
|
|
754 |
\subsubsection{Offset texture} |
\subsubsection{Image-space algorithms} |
755 |
|
|
756 |
|
Image-space algorithms for drawing edges\cite{saito90comprehensible} |
757 |
|
work somewhat analogously to the previous section; the difference |
758 |
|
is that instead of rendering the shape several times, |
759 |
|
a filter is applied |
760 |
|
to the depth buffer where the shapes have been rendered |
761 |
|
to extract the discontinuities. |
762 |
|
|
763 |
|
The advantage of image-space algorithms is that their performance |
764 |
|
does not depend on the complexity of a scene; however, it appears |
765 |
|
that NV30/R300 generation of graphics chips is flexible enough |
766 |
|
to support image-based operations well, due to the number of texture |
767 |
|
accesses and floating point operations needed. Also, it is more |
768 |
|
difficult (although possible) |
769 |
|
to adjust the width of the border based on depth |
770 |
|
in this approach. |
771 |
|
|
772 |
Because the algorithm for drawing the shape is |
|
773 |
equivalent to one-dimensional offsetting of a half-plane, |
\subsubsection{A silly hack with offset texture mipmapping} |
774 |
the border can be drawn by offsetting |
|
775 |
|
The border can be drawn by offsetting |
776 |
a texture with an image of a straight line. |
a texture with an image of a straight line. |
777 |
However, a sloped offset reduces the width of the distorted line. |
However, a sloped offset reduces the width |
778 |
|
of the distorted line. |
779 |
|
This narrowing can be compensated by |
780 |
|
using |
781 |
|
scale-invariant constant line width (in texels) |
782 |
|
for the mipmaps of the image of the line. |
783 |
|
|
784 |
This problem can be overcome by computing the mipmaps of |
The trick is that the computed level of detail |
785 |
the edge texture with scale-invariant constant line width (in texels). |
for each fragment (at least on the NV25) is lower for a |
|
The computed level of detail for each fragment is lower for a |
|
786 |
sloped offset, and the lower detail texture with thicker line |
sloped offset, and the lower detail texture with thicker line |
787 |
will exactly compensate the reduced line width. |
will exactly compensate the reduced line width. |
788 |
Note that this no longer holds for two-dimensional offsetting. |
Note that this only holds when offsetting in the normal direction. |
789 |
Also, derivative discontinuities are sometimes visible |
Also, derivative discontinuities are sometimes visible |
790 |
as spikes in the border, if the border is more |
as spikes in the border, if the border is more |
791 |
than a few pixels wide. |
than a few pixels wide. FIG |
|
|
|
|
The edge texture can be one texel wide (if the image of the |
|
|
edge is drawn horizontally), allowing for large height and |
|
|
so non-photorealistic scaling to large scales. |
|
|
Note that it still has to be a 2D texture for the mipmapping trick |
|
|
to work. |
|
792 |
|
|
793 |
Increasing the border width scaling exponent from 0 makes the |
This trick only works if the line texture is 2D, but its other dimension can |
794 |
border width less consistent with sloped offset. |
be 1. |
795 |
|
|
796 |
\subsection{Future work: NV30 and R300} |
% XXX really? |
|
|
|
|
XXX |
|
797 |
|
|
798 |
With NV30, more accuracy with floating point textures. |
% The edge texture can be one texel wide (if the image of the |
799 |
More procedural textures with fragment programs. |
% edge is drawn horizontally), allowing for large height and |
800 |
A single texture unit can be accessed multiple |
% so non-photorealistic scaling to large scales. |
801 |
times with displaced texture coordinates computed in a fragment program. |
% Note that it still has to be a 2D texture for the mipmapping trick |
802 |
|
% to work. |
803 |
|
% |
804 |
|
% Increasing the border width scaling exponent from 0 makes the |
805 |
|
% border width less consistent with sloped offset. |
806 |
|
|
807 |
\subsection{Tearout shapes} |
\subsection{Polygonal undistorted shapes} |
808 |
|
|
809 |
In earlier sections, we have presented different ways of drawing |
In the previous sections we have presented different ways of drawing |
810 |
one linear section of the envelope. |
one linear section of the envelope. |
811 |
In this section, we consider different ways of drawing complete |
In this section, we consider different ways of drawing complete |
812 |
tear-out shapes with contents. |
tear-out shapes with contents. |
962 |
|
|
963 |
\section{Conclusions} |
\section{Conclusions} |
964 |
|
|
965 |
|
|
966 |
|
XXX |
967 |
|
|
968 |
|
With NV30, more accuracy with floating point textures. |
969 |
|
More procedural textures with fragment programs. |
970 |
|
A single texture unit can be accessed multiple |
971 |
|
times with displaced texture coordinates computed in a fragment program. |
972 |
|
|
973 |
|
|
974 |
frequencies: only low/high in frames |
frequencies: only low/high in frames |
975 |
|
|
976 |
interaction with libpaper!!! |
interaction with libpaper!!! |
1007 |
The authors would like to thank \censor{Benja Fallenstein and |
The authors would like to thank \censor{Benja Fallenstein and |
1008 |
Antti-Juhani Kaijanaho} for discussions. |
Antti-Juhani Kaijanaho} for discussions. |
1009 |
|
|
1010 |
|
% References contain hard-to-typeset parts -- help TeX out a bit |
1011 |
|
\hbadness=4000 |
1012 |
|
|
1013 |
\bibliographystyle{plain} |
\bibliographystyle{plain} |
1014 |
\bibliography{gzigzag} |
\bibliography{gzigzag} |
1015 |
|
|