11

In the section called General (Functional) Shadings in the PGF/TikZ manual, there is an "explanation" of the command to create a general functional shading.

The author of this section assumes that the TeX user knows how to use the type 4 function.

But I don't, so where can I learn? Can somebody explain how to create a shading with this command?

4
  • 3
    The pgfmanual mentions a number of caveats with the functional shadings (These shadings are the least portable of all and they put the heaviest burden of the renderer. They are slow and, possibly, will not print correctly!). Maybe you could explain what you are trying to achieve so people might suggest other avenues to explore.
    – Jake
    Sep 19, 2011 at 3:42
  • Also they will not render correctly in many PDF viewers.
    – Caramdir
    Sep 19, 2011 at 3:52
  • @Jake: consider a function defined in a polar system like (1/r)*(cos(theta))^2. I'd like to create a rectangular shading that goes from red to blue that follow the previou equation.
    – Azoun
    Sep 19, 2011 at 12:37
  • @Azoun: With that function, there are a couple of problems due to the singularity at r=0. What value do you want to assign to red, what value to blue? What do you want to do near r=0?
    – Jake
    Sep 19, 2011 at 13:05

3 Answers 3

7

The type 4 functions mentioned in the TikZ manual are what are called Postscript Calculator Functions, a subset of Postscript which is supported by the PDF specification. The actual subset is described in chapter 7 of the PDF 1.7 reference manual. Type 4 functions themselves are described in detail in Chapter 4 of the Postscript Language Reference 3rd Edition.

Unless you are well versed in the Postscript language, I don't think this aspect of PGF is very accessible.

12

I don't know any good place from where to learn all the material, but I can try to give you a few pointers. The following comes with the caveat that I only dabbled in writing shaders a bit and am certainly no expert on this topic.

Abstractly, a functional shader is given by a function f: R → [0,1]³, where R is some subset of ℝ² (usually a rectangle) and [0,1]³ is interpreted as the space of all RGB colors. So f assigns each point of the shaded region a color. Your job is to provide f. Then, each time the image is rendered the viewer evaluates f on (the point of R corresponding to) each pixel inside the image and colors the pixel with the returned color.

In PGF, you'd specify such a function with \pgfdeclareshading:

\pgfdeclarefunctionalshading
    {⟨shading name⟩}
    {⟨lower left corner⟩}{⟨upper right corner⟩}
    {⟨initialization code⟩}
    {⟨code for the actual shading⟩}

Here {⟨lower left corner⟩}{⟨upper right corner⟩} specifies the rectangular domain R ⊆ ℝ², ⟨initialization code⟩ can be ignored for the moment (see the PGF manual for details) and ⟨code for the actual shading⟩ is the difficult part.

The actual code for the shading has to be written in a very restricted subset of PostScript. Presumably it is so restricted to force you to only write very simple function. Even so, be aware that the rendering of a shading can take a very long time (and has to be done each time the document is displayed).

PostScript is a stack-based programming language. If you are not familiar with this concept, try reading the Wikipedia article on that subject. If you are not used to stack-based languages, be aware that writing even very simple functions can be a challenge.

The allowed subset is listed in the PGF manual or the PDF reference: basically you only have math functions, stack manipulation operators and if-then-else at your disposal. You'll notice that there are no loops and variables. The operations themselves are described in section 3.6 of the Postscript Language Reference 3rd Edition or presumably any other good book about PostScript (see for example Wikipedia's references).

At the start of the execution of the shader function the stack consists of the x and y coordinate of a point in R (in big points) and after the execution the top three stack elements should be real values in [0,1] which are treated as red, green and blue component of the color of this point.

2
  • Many thanks for the stack-based programming language wikipedia page. I didn't know this concept before.
    – Azoun
    Sep 19, 2011 at 12:40
  • 2
    @Azoun ever looked at what the URL of this forum is? ;)
    – percusse
    Sep 19, 2011 at 20:43
10

As a different approach to creating complicated shadings: You could use a three-dimensional pgfplots plot that is viewed from above, and use the colormap feature to get the colours.

For example, the shading mentioned in your comment, (1/r)*(cos(theta))^2 in a polar coordinate system, could be achieved like this:

\documentclass{article}
\usepackage[]{pgfplots}

\begin{document}
\begin{tikzpicture}
\pgfplotsset{colormap={redblue}{rgb(0cm)=(1,0,0); rgb(1cm)=(0,0,1)}}
\begin{axis}[
    view={0}{90},
    width=7cm, height=7cm,
    xmin=-0.707, xmax=0.707, ymin=-0.707, ymax=0.707,
    hide axis]
\addplot3 [
    domain=0:360,
    y domain=0.1:1,
    surf,
    shader=interp
    ] ({y*cos(x)},
        {y*sin(x)},
        {(1/y)*(cos(x))^2});
\end{axis}
\end{tikzpicture}
\end{document}

Note that there is a singularity at r=0 due to the term 1/r, that's why there's a hole in the middle. The smaller the hole, the less interesting the shading.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .