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.
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.tex • hsv-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.