Published 2008-10-27 | Author: Ken Starks

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.

Source: PGF-users mailing list

Do you have a question regarding this example, TikZ or LaTeX in general? Just ask in the LaTeX Forum.
Oder frag auf Deutsch auf TeXwelt.de. En français: TeXnique.fr.

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

\begin{document}

{\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

%the interval [0, 1.0]
ifelse  % because we will use it for 'Hue'
dup 360 eq { pop 0.0 }{} ifelse % if heading is 360

3 1 roll % ... heading x y
dup mul % ... heading x y*y
exch dup mul % ... heading y*y x*x

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}
%\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)


• #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 support fadings with varying alpha-values.