PGF supports several types of shadings. The most advanced type of shading is "functional shadings". For such shadings the color of each point is calculated by calling a user specified function for each point in the shaded area. The shading function is specified using a simplified form of a subset of the PostScript language.

In this impressive example a functional shading is used to draw a slice of the cone shaped HSV color space. Note the smooth color transitions. The most interesting part of the code is the conversion from HSV to RGB.


hsv-shading

Edit and compile if you like:

% HSV shading
% Author: Ken Stars
\documentclass{article}
\usepackage{tikz}


\begin{document}


\pgfdeclarefunctionalshading{HSVsweep}
{\pgfpoint{-2cm}{-2cm}}
{\pgfpoint{2cm}{2cm}}
{}
{ % x y
 2 copy % ... x y x y
 2 copy 0 eq exch 0 eq and
 { pop pop 0.0 } % silently deal with error: return
               % arbitrary heading of zero for origin
 {atan 360.0 div} % ... x y heading;  heading being in
                 %the interval [0, 1.0]
 ifelse  % because we will use it for 'Hue'
 dup 360 eq { pop 0.0 }{} ifelse % if heading is 360
                                 %degrees, make it zero instead
 3 1 roll % ... heading x y
 dup mul % ... heading x y*y
 exch dup mul % ... heading y*y x*x
 add sqrt % ... heading ra_pt (distance from origin in points)
 56 div % scale it means a ra of just under 2 cm
 dup 1.0 ge % BOOLEAN. ready to clamp to interval [0, 1.0]
 { pop 1.0 }{} ifelse % We shall use the scaled ra as 'Saturation'
 2.5 mul 0.25 sub % now, Ra in [0.1, 0.5] --> Saturation
                % in [0.0, 1.0]. Saturation varies between the two radii
 1 % ... H S V ( with 'Value' set to literal constant of 1.0 )
 1 index 1.0 eq % TEST I [ S == 1.0 ]
 { % BLOCK A [ take stack to V V V ] achromatic case
   3 1 roll pop pop dup dup
 }
 { % BLOCK B take stack to V T Q P i
   % C version to use as model:
     % H' = H * 6
     % i = floor(H')
     % f = H' - i
     % P = V * (1.0 - S)
     % Q = V * (1.0 - (S*f))
     % T = V * (1.0 - (S * (1.0 - f)))
   3 -1 roll 6.0 mul dup 4 1 roll % H' S V H'
   floor % H' S V i
   dup  5 1 roll % i H' S V i
   3 index sub neg % i H' S V f
   1.0 3 index sub % i H' S V f (1.0 - S )
   2 index mul % i H' S V f P
   6 1 roll % P i H' S V f
   dup 3 index mul neg 1.0 add % P i H' S V f ( 1.0 - (f*S))
   2 index mul % P i H' S V f Q
   7 1 roll % Q P i H' S V f
   neg 1.0 add % Q P i H' S V (1.0 - f)
   2 index mul neg 1.0  add % Q P i H' S V (1.0 - S * (1.0 - f))
   1 index mul % Q P i H' S V T
   7 2 roll % V T Q P i H' S
   pop pop % V T Q P i
   %%%
   % end of BLOCK B. The rest is just stack manipulation
   dup 0 eq % TEST II [ i == 0 ]
   { % BLOCK C [ take stack to V T P ]
   pop exch pop
   }
   { dup 1 eq % TEST III [ i == 1 ]
     { % BLOCK D [ take stack to Q V P ]
   pop exch 4 1 roll exch pop
     }
     { dup 2 eq % TEST IV [ i == 2 ]
       { % BLOCK E [ take stack to P V T ]
       pop 4 1 roll pop
       }
       { dup 3 eq % TEST V [ i == 3 ]
         { % BLOCK F [ take stack to P Q V ]
         pop exch 4 2 roll pop
         }
         { dup 4 eq % TEST VI [ i == 4 ]
           { % BLOCK G [ take stack to T P V ]
           pop exch pop 3 -1 roll
           }
           { % BLOCK H [ take stack to V P Q ]
           pop 3 1 roll exch pop
           }
           ifelse
         }
         ifelse % for V
       }
       ifelse % for IV
     }
     ifelse % for III
   }
   ifelse % for II
   % BLOCK I
 }
 ifelse % for I
 % BLOCK J
 % .. RGB at last
 % Fix for Apple's PDF viewer shading bug:
 cvr 3 1 roll cvr 3 1 roll cvr 3 1 roll 
}

\begin{tikzpicture}
 \def\ra{3.8cm}
 \def\raB{1cm}
    \draw[shading=HSVsweep,even odd rule] (0,0) circle (\ra) circle (\raB);
    \foreach \x  in {0, 30, ..., 330}
        \draw (-\x+90:3.8) -- (-\x+90:4.0) (-\x+90:4.4) node {$\x^\circ$};
\end{tikzpicture}

% The shading can also be used for other shapes
%\begin{tikzpicture}
%    \draw[shading=HSVsweep,shading angle=90] (0,0) rectangle (4,8);
%\end{tikzpicture}

\end{document}


See:
James D FOLEY et al
"Computer Graphics, Principals and Practice"
2nd edition
ISBN 0-204-84840-6

Page 593. Figure 13.34
"Algorithm for converting from HSV to RGB color space"
(This is C. I had to convert it to Postscript. Mostly
lots of nasty stack manipulation)





Click to download: hsv-shading.texhsv-shading.pdf
Open in Overleaf: hsv-shading.tex


Comments

#1 Kjell Magne Fauske, October 29, 2008 at 8:33 a.m.
Update: Added a workaround for Apple’s PDF viewer shading bug. Thanks Berteun Damman for the patch.

#2 hakan tiftikci, November 11, 2009 at 8:40 a.m.
can alpha channel (~transparency) be specified in “functional shadings”?

#3 Kjell Magne Fauske, November 13, 2009 at 10:41 a.m.
I checked the PGF documentation, but as far as I can see, you can’t specify alpha channel when using functional shadings, only RGB-values. There are probably workarounds since PGF supports fadings with varying alpha-values.