Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Optical illusions are fun, so I thought it would be a good idea to have a list of optical illusions designed using MetaPost, or PGF/TikZ, or PS-Tricks, or Asymptote. Each entry should display one optical illusion and the code necessary to produce it.

share|improve this question
3  
+1 for MP examples, but I still don't see why questions like this should be CW. I plan on asking a meta question about this, but for now read The Future of community Wiki. –  Sean Allred Aug 20 '13 at 20:03
    
Besides some lines that do not appear to be straight or parallel or of equal length but in fact are, the Spinning Dancer would be an interesting project. –  Qrrbrbirlbel Aug 20 '13 at 21:10
    
@Qrrbrbirlbel indeed. Go for it! –  Gonzalo Medina Aug 20 '13 at 22:09
add comment

15 Answers 15

Don't stare at this one for too long.

\documentclass{standalone}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}
  \fill[color=black!40!white] (-6,-6) rectangle (6,6);
  \foreach \n/\r/\twist in {70/5/12,56/4/-12,42/3/12,28/2/-12}{
    \foreach \m in {1,3,...,\n}
      \draw [thick,color=white,shift={(360/\n*\m:\r)},rotate=\twist+360/\n*\m]
        (-.15,-.15) rectangle (.15,.15);
    \foreach \m in {2,4,...,\n}
      \draw [thick,color=black,shift={(360/\n*\m:\r)},rotate=\twist+360/\n*\m]
        (-.15,-.15) rectangle (.15,.15);
    }
\end{tikzpicture}

\end{document}

enter image description here

share|improve this answer
19  
That's ridiculously deceiving... –  Werner Aug 20 '13 at 23:37
2  
I tried counting the circles. My brain refused, even though I know how many there are. –  naught101 Aug 21 '13 at 5:53
    
Circles? Isn't it a spiral? :-) –  mhelvens Aug 21 '13 at 6:22
3  
@naught101 Why would you count them? This is a mathematics site, just draw a line across the drawing and count the intersections :p –  Thomas Aug 21 '13 at 10:12
    
@Thomas That's clever! –  gekkostate Aug 21 '13 at 14:25
show 4 more comments

The following graphics are shamelessly copied from the MetaFun manual and coded by Hans Hagen. The title is: Manupulating contrast by changing spatial configuration. The graphics originate from the psychologist Kurt Koffka.

result

\starttext

\startuseMPgraphic{first}
  numeric height, width, radius, gap ; gap := 1mm ;
  height = 2.5cm ; width := height/2 ; radius := height/2.5 ;
  color mainshade, leftshade, rightshade, centershade ;
  mainshade   := \MPcolor{lightblue} ;
  leftshade := .9mainshade ; rightshade := .5mainshade ;
  centershade := .5[leftshade,rightshade] ;
  fill unitsquare xyscaled ( width,height) withcolor leftshade ;
  fill unitsquare xyscaled (-width,height) withcolor rightshade ;
  draw (fullcircle scaled radius) shifted (0,height/2)
  withpen pencircle scaled (radius/2) withcolor centershade ;
\stopuseMPgraphic

\startuseMPgraphic{second}
  \includeMPgraphic{first}
  interim linecap := butt ; pickup pencircle scaled gap ;
  draw (0,0) -- (0,height) withcolor white ;
\stopuseMPgraphic


\startuseMPgraphic{third}
  \includeMPgraphic{first}
  picture p, q ; p := q := currentpicture ;
  clip p to unitsquare xscaled width yscaled height ;
  clip q to unitsquare xscaled -width yscaled height ;
  currentpicture := p ;
  addto currentpicture also q shifted (0,radius/2) ;
\stopuseMPgraphic

\useMPgraphic{first}
\useMPgraphic{second}
\useMPgraphic{third}

\stoptext
share|improve this answer
1  
What is the illusion? –  gerrit Aug 21 '13 at 11:37
5  
When the circle is taken apart and shifted, the right half of the circle appears to be darker than the left half. But the circle has one uniform colour. –  Marco Aug 21 '13 at 11:42
1  
Hm. They look the same colour to me. –  gerrit Aug 21 '13 at 11:46
3  
Most people perceive both halfs to be different shades, maybe you are not affected. A psychologist may be able to draw interesting conclusions from this. ;) –  Marco Aug 21 '13 at 11:56
    
How do you compile this? I tried using context <file_name>, but all I get is a log and a tuc file. –  A.Ellett Sep 5 '13 at 4:29
show 2 more comments

The radius of both orange circles is the same- this is Ebbinghaus' illusion

enter image description here

% arara: pdflatex
% !arara: indent: {overwrite: yes}
\documentclass{standalone}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[baseline=(X.base)]
    \node[circle,fill=orange,draw=orange,minimum size=2cm] (X) at (0,0) {};
    \foreach \i in {0,60,...,330}{
        \filldraw[blue!50!white]  (\i:3.4) circle (1.6);}
\end{tikzpicture}
\hspace{1cm}
\begin{tikzpicture}[baseline=(X.base)]
    \node[circle,fill=orange,draw=orange,minimum size=2cm] (X) at (0,0) {};
    \foreach \i in {0,45,...,360}{
        \filldraw[blue!50!white]  (\i:1.5)  circle (.4);}
\end{tikzpicture}
\end{document}
share|improve this answer
3  
Maybe are the colors or the distance between the circles that differ from the ones on the wikipedia picture but, the circles look the same to me in this picture. –  キキジキ Aug 21 '13 at 3:50
    
I think it is the size of the surrounding circles around the left circle. They are not as big as in the Wikipedia picture. –  Andres Riofrio Aug 21 '13 at 4:47
    
Maybe put them further apart? –  naught101 Aug 21 '13 at 5:54
2  
@AndresRiofrio yes, probably is the size of the surrounding circles in the left, they should be bigger than the one in the center. –  キキジキ Aug 21 '13 at 9:56
1  
@cmhughes nice, looks more effective now. –  キキジキ Aug 21 '13 at 14:25
show 1 more comment

With PSTricks.

\documentclass[pstricks,border=12pt]{standalone}
\newpsstyle{gridstyle}
{
    gridlabels=0,
    gridwidth=6pt,
    subgriddiv=1,
    gridcolor=gray,
}
\begin{document}
\begin{pspicture}(8,8)
    \psframe*(8,8)
    \psgrid[style=gridstyle]
    \psset{linecolor=white}
    \multips(0,1)(0,1){7}{\multips(1,0)(1,0){7}{\qdisk(0,0){4.242pt}}}
\end{pspicture}
\end{document}

enter image description here

share|improve this answer
2  
Why PSTricks? The picture code would be almost the same ;) –  tohecz Sep 5 '13 at 9:13
3  
@tohecz: There are only two options: with PSTricks or without PSTricks. :-) –  Please don't touch Sep 5 '13 at 10:56
add comment

The following graphic is shamelessly copied from the MetaFun manual and coded by Hans Hagen. The title is: White's illusion.

result

\starttext
  \startMPcode
    interim linecap := butt ; numeric u ; u := 1cm ;
    pickup pencircle scaled .5u ;
    for i=1u step u until 5u :
      draw (0,i) -- (5u,i) ;
    endfor ;
    for i=2u step u until 4u :
      draw (u,i) -- (2u,i) withcolor .5white ;
      draw ((3u,i) -- (4u,i)) shifted (0,-.5u) withcolor .5white ;
    endfor ;
  \stopMPcode
\stoptext
share|improve this answer
add comment

They are or not parallels?

A very popular one.

The perpendicular lines that do not match row to row create an illusion of the lines between them being not parallel. NetLogo Models Library: Optical Illusions

Parallels

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\begin{document}
    \pagecolor{gray}
    \begin{tikzpicture}
        \pgfmathsetmacro{\offsety}{.05};
        \foreach \y / \offsetx in {0/0.3,1/0.5,2/0.3,3/0,4/0.3,5/0.5,6/0.3,7/0,8/0.3}
            \foreach \x in {0,...,10}{%
                \pgfmathifthenelse{mod(\x,2) == 0}{"black"}{"white"}
                %\ifodd\x \def\squarecolor{white} \else \def\squarecolor{black} \fi %Other way, use \squarecolor inside fill options
                \fill[\pgfmathresult] ($(\x,\y)+(\offsetx,\offsety*\y)$) rectangle +(1,1);
            }
    \end{tikzpicture}
\end{document}
share|improve this answer
add comment

With PSTricks.

\documentclass[pstricks,border=12pt]{standalone}
\SpecialCoor
\def\Less(#1,#2){\psline[origin={#1,#2}](1;30)(0,0)(1;-30)}
\def\Greater(#1,#2){\psline[origin={#1,#2}](1;150)(0,0)(1;-150)}

\begin{document}
\begin{pspicture}(-4,-3)(4,3)
    \psline(-2,2)(2,2)
    \Less(-2,2)
    \Greater(2,2)
    %
    \psline(-2,-2)(2,-2)
    \Less(2,-2)
    \Greater(-2,-2)
\end{pspicture}
\end{document}

enter image description here

share|improve this answer
1  
I was missing your answer :-) –  Gonzalo Medina Sep 3 '13 at 22:49
add comment

Here is one in metapost

path p[],tread[],riser[];
picture pic[];
color treadc;

a:=3;       A:=a; % steps from left to top
b:=8;       B:=a+b; % steps from top to right
c:=b-1;     C:=a+b+c; % steps from right to bottom
d+c=a+b;    D:=a+b+c+d; % steps from bottom to lefttheta:=25;
theta:=25;
u:=1cm;
dy=u*sind(theta)/cosd(theta);
p0:=(0,0)--(u,dy)--(2u,0)--(u,-dy)--cycle;
treadc:=(.8,.75,.7);

beginfig(1)
  % define leftmost corner of each tread, also define riser implicitly
  z0=(0,0) =z[D];
  for i =   1 upto A: z[i]=z[i-1]+( u, dy+riser); endfor;
  for i = A+1 upto B: z[i]=z[i-1]+( u,-dy+riser); endfor;
  for i = B+1 upto C: z[i]=z[i-1]+(-u,-dy+riser); endfor;
  for i = C+1 upto D: z[i]=z[i-1]+(-u, dy+riser); endfor;
  treadht:=.3riser;
  % paths for treads
  for i = 0 upto D-1:
    tread[i]:= p0 shifted z[i];
    fill tread[i] withcolor treadc;
    draw tread[i];
  endfor
  tread[D]=tread[0];
  % points for building
  z0o=point 0 of tread0;        z0i=point 2 of tread0;
  z[A]o=point 1 of tread[a];    z[A]i=point 3 of tread[a];
  z[B]o=point 2 of tread[B];    z[B]i=point 0 of tread[B];
  z[C]o=point 3 of tread[C];    z[C]i=point 1 of tread[C];
  z0l=z0o +(0,-D*dy/2);
  z[C]l=z[C]o + whatever*down = z0l+whatever*(u,-dy);
  z[B]l=z[B]o + whatever*down = z[C]l+whatever*(u,dy);
  % paths for risers
  for i = 0 upto a-1:
    riser[i]:=subpath(1,2) of tread[i] -- subpath(3,4) of tread[i+1] -- cycle;
    fill riser[i] withcolor .6white;
    draw riser[i];
    draw subpath(2,3) of riser[i] shifted (0,-treadht) withcolor .3treadc;
  endfor
  for i = a upto B-1:
    riser[i]:=subpath(2,3) of tread[i] -- subpath(0,1) of tread[i+1] -- cycle;
  endfor
  for i = B upto C-1:
    riser[i]:=subpath(3,4) of tread[i] -- subpath(1,2) of tread[i+1] -- cycle;
  endfor
  for i = C upto D-1:
    riser[i]:=subpath(0,1) of tread[i] -- subpath(2,3) of tread[i+1] -- cycle;
    fill riser[i] withcolor .6white;
    draw riser[i];
    draw subpath(2,3) of riser[i] shifted (0,-treadht) withcolor .3treadc;
  endfor
  % clipping path for inside
  p1:=point 2 of tread0 --
    for i=1 upto a-1:  subpath (3,2) of tread[i] -- endfor
    for i=a+1 upto B-2: subpath(4,3) of tread[i] -- endfor
    (subpath(4,3) of tread[B-1] cutafter tread[B+1]) --
    for i=B+1 upto C-1: (subpath(1,0) of tread[i] cutafter  tread[i+1]) -- endfor
    point 1 of tread[C] --
    for i = C+1 upto D-1: subpath(2,1) of tread[i] -- endfor
    cycle;
  % clipping path for outside
  p2:=for i = B upto C: subpath(2,3) of tread[i] -- endfor
    for i = C upto D: subpath(3,4) of tread[i] -- endfor
    z0l--z[C]l--z[B]l--cycle;
  % inside wall picture
  pic1=image(
    p99:=z0i--(z0i+(a-1)*(u,dy))--(z0i+(a-1)*(u,dy)+(b-1)*(u,-dy));
    p99:=p99--(reverse p99 shifted (0,-riser))--cycle;
    M:=D*dy/riser;
    for i = -B upto M:
      fill p99 shifted (0,-i*riser) withcolor .2[(.5-.6*i/M)*white,if odd(i+B): (.7,.7,.6) else: (.1,.1,0) fi];
      draw p99 shifted (0,-i*riser) withcolor .2white;
    endfor
    draw z[a]i--(z[a]i+D*dy*down);
    );
  fill p1 withcolor treadc;
  clip pic1 to p1;
  pic1:=image(
    draw pic1 shifted (0,-treadht);
    draw p1 shifted (0,-treadht)withcolor .3treadc;
    );
  clip pic1 to p1;
  draw pic1;
  draw p1;
  % outside wall picture
  pic2=image(
    p99:=(0,0)--((d+1)*(u,-dy))--((d+1)*(u,-dy)+(c+1)*(u,dy));
    p99:=p99--(reverse p99 shifted (0,-riser))--cycle;
    M:=D*dy/riser;
    for i = 0 upto M:
      fill p99 shifted (0,-i*riser) withcolor .2[(.7-.6*i/M)*white,if odd(i): (1,1,.8) else: (.2,.2,0) fi];
      draw p99 shifted (0,-i*riser) withcolor .4white;
    endfor
    draw z[C]o--z[C]l;
    );
  fill p2 withcolor treadc;
  clip pic2 to p2;
  pic2:=image(
    draw pic2 shifted (0,-treadht);
    draw p2 shifted (0,-treadht)withcolor .3treadc;
    );
  clip pic2 to p2;
  draw pic2;
  draw p2;
endfig;

bye

enter image description here

share|improve this answer
add comment

enter image description here

Another old illusion with lualatex and METAPOST

\documentclass{standalone}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
beginfig(1);
numeric a,b; path rhomb;
a:=2cm; b:=sqrt(3)/2*a;
rhomb:=(b,0)--(0,a/2)--(-b,0)--(0,-a/2)--cycle;

picture rhombs;
rhombs := image(
  fill rhomb shifted ( b,0);  fill rhomb shifted (0, 3a/2);  
  fill rhomb shifted (-b,0);  fill rhomb shifted (0,-3a/2);
);

draw rhombs withcolor red;
draw rhombs rotated 120 withcolor green;
draw rhombs rotated -120 withcolor blue;

endfig;
end.
\end{mplibcode}
\end{document}
share|improve this answer
add comment

Here is an Escher brick and a Penrose triangle; I submitted this code to texample a while back but I've only just seen this question.

enter image description here

\documentclass{article}
\usepackage{tikz}
\begin{document}
  \begin{center}
    \begin{tikzpicture}[scale=4.5, line join=bevel]

      % \a and \b are two macros defining characteristic
      % dimensions of the impossible brick.
      \def\a{0.18}
      \def\b{1.37}

      \tikzset{%
        apply style/.code={\tikzset{#1}},
        brick_edges/.style={thick,draw=black},
        face_colourA/.style={fill=gray!50},
        face_colourB/.style={fill=gray!25},
        face_colourC/.style={fill=gray!90},
      }

      \foreach \theta/\v/\facestyleone/\facestyletwo in {%
        0/0/{brick_edges,face_colourA}/{brick_edges,face_colourC},
        180/-\a/{brick_edges,face_colourB}/{brick_edges,face_colourC}
      }{
      \begin{scope}[rotate=\theta,shift={(\v,0)}]
        \draw[apply style/.expand once=\facestyleone]       
          ({-.5*\b},{1.5*\a}) --
          ++(\b,0)            --
          ++(-\a,-\a)         --
          ++({-\b+2*\a},0)    --
          ++(0,-{2*\a})       --
          ++(\b,0)            --
          ++(-\a,-\a)         --
          ++(-\b,0)           --
          cycle;
        \draw[apply style/.expand once=\facestyletwo] 
          ({.5*\b},{1.5*\a})  --
          ++(0,{-2*\a})       --
          ++(-\a,0)           --
          ++(0,\a)            --
          cycle;
        \end{scope}
      }
    \end{tikzpicture}

    \vspace{1cm}

    \begin{tikzpicture}[scale=1, line join=bevel]

    % \a and \b are two macros defining characteristic
    % dimensions of the Penrose triangle.       
    \def\a{2.5}
    \def\b{0.9}

    \tikzset{%
      apply style/.code     = {\tikzset{#1}},
      triangle_edges/.style = {thick,draw=black}
    }

    \foreach \theta/\facestyle in {%
        0/{triangle_edges, fill = gray!50},
      120/{triangle_edges, fill = gray!25},
      240/{triangle_edges, fill = gray!90}%
    }{
      \begin{scope}[rotate=\theta]
        \draw[apply style/.expand once=\facestyle]
          ({-sqrt(3)/2*\a},{-0.5*\a})                     --
          ++(-\b,0)                                       --
            ({0.5*\b},{\a+3*sqrt(3)/2*\b})                -- % higher point 
            ({sqrt(3)/2*\a+2.5*\b},{-.5*\a-sqrt(3)/2*\b}) -- % rightmost point
          ++({-.5*\b},-{sqrt(3)/2*\b})                    -- % lower point
            ({0.5*\b},{\a+sqrt(3)/2*\b})                  --
          cycle;
        \end{scope}
      } 
      \end{tikzpicture}
  \end{center}
\end{document}
share|improve this answer
add comment

enter image description here

Demonstration of the physiological blind spot in our vision, see wiki for details.

Edit Apparently, the wiki link was not enough, some comments are due. Every eye has a blind spot, which presence can be discovered only with the other eye closed. Demonstration of the blind spot in the wiki uses just two letters, R and L one is used to focus on, the other as an object to disappear from the sight. The image above improves the demonstration and allows to estimate a size of the blind spot, since while the blue ball disappears, the big red ring stays visible.

Instructions: Close one eye and focus the other on the appropriate small green ball. Place your eye a distance from the screen (or maybe better to use a printed version) approximately equal to 3x the distance between the green and the blue ball. Move your eye towards or away from the screen until you see the blue ball inside a red ring disappear. For example, close your right eye, look at the Left eye green ball with your left eye, and the blue ball will disappear from within the big red ring.

% lusion.tex:
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}

\begin{document}
\begin{figure}
\begin{asy}
unitsize(2mm);

real r0,r1,r2,r3;
r0=1;
r1=4;
r2=10;
r3=15;
pair O=(0,0);
pair dotC=(2r3,0);

void ball(pair c,real r1,real r2=0.07r1,pen p1,pen p2){
  radialshade(circle(c,r1), p1,c,r2,p2,c,r1); 
}

ball(O,r3,r2,white,red);
fill(circle(O,r2),white);
ball(O,r1,white,darkblue);

ball(-dotC,r0,lightgreen,darkgreen);
ball(dotC,r0,lightgreen,darkgreen);

defaultpen(fontsize(10pt));
label("Right eye",-dotC,2N);
label("Left eye",dotC,2N);
\end{asy}
\caption{Demonstration of the blind spot}
\end{figure}
\end{document}

% To process it with `latexmk`, create file `latexmkrc`:
% 
%     sub asy {return system("asy '$_[0]'");}
%     add_cus_dep("asy","eps",0,"asy");
%     add_cus_dep("asy","pdf",0,"asy");
%     add_cus_dep("asy","tex",0,"asy");
% 
% and run `latexmk -pdf lusion.tex`.
share|improve this answer
2  
I cannot control my left eye to see the right green ball and my right eye to see the left green ball at the same time. –  Please don't touch Sep 4 '13 at 0:54
1  
@PSTikZ: OMG, you tried what?! I haven't heard anything that funny for quite a while, you made my day :) It's my bad, I should add the instructions, I just thought the wiki link would be enough. See the instructions added. –  g.kov Sep 4 '13 at 9:37
2  
I wasn't able to move my eye towards the screen, since my eye is fixed inside my eye socket. ;) –  Sverre Sep 4 '13 at 10:13
    
@Sverre: :) It would be more convenient to print the picture (could be B/W, colors are not important here) and move the paper sheet instead. –  g.kov Sep 4 '13 at 11:08
    
I don't know about that. I could easily find my blind spots by moving my head. Pretty cool. –  Sverre Sep 4 '13 at 11:33
add comment

Without PSTricks.

I don't know whether or not the following can be regarded as an optical illusion. The extra delay in trying to say the word when it's colored differently is known as the Stroop effect.

\documentclass[preview,border=12pt,varwidth,dvipsnames]{standalone}
\usepackage{xcolor}
\begin{document}
Speak loudly and quickly the color for each item below:
\Huge\bf
\begin{itemize}
    \item \textcolor{red}{Black}
    \item \textcolor{blue}{Red}
    \item \textcolor{yellow}{Green}
    \item \textcolor{green}{Magenta}
    \item \textcolor{cyan}{Pink}
    \item \textcolor{black}{Cyan}
    \item \textcolor{red}{Blue}
    \item \textcolor{yellow}{Maroon}
    \item \textcolor{orange}{Magenta}
    \item \textcolor{red}{Yellow}
\end{itemize}
\end{document}

enter image description here

share|improve this answer
    
Children who have not learnt reading can speak the color faster than you! So stop underestimating them! –  Please don't touch Nov 6 '13 at 16:22
add comment

Beautiful curved grid?

A variant and a combination of Hering's and Zöllner's illusion. The red grid is completely straight all the time.

enter image description here

Code

\documentclass[border=10pt,tikz]{standalone}
\pagecolor{gray!5}
\begin{document}
    \begin{tikzpicture}[x=4cm,y=4cm,every rectangle node/.style={draw,thick,red,rotate=45,minimum width=0.707*4cm,minimum height=0.707*4cm}]
        \foreach \y in {1,...,3}
            \foreach \x in {1,...,3}{%
                \foreach \diameter in {1,...,6}
                    \draw[gray,thick] (\x,\y) circle (1/12*\diameter);
                \node[rectangle] at (\x,\y) {};
            }
    \end{tikzpicture}
\end{document}

A great website with optical illusions can be found here.

share|improve this answer
add comment

Another metapost illusion - one of my favourite "local colour" illusions. The three identified points are all of the same colour.

The penumbra code is a bit of a hack, as metapost has no transparency.

picture TeX[],checks[];
path p[],p[]trim[];
color shade[];
transform T[];

%need to draw grids with different light, dark cells, so a function for this
def gridpic(expr wd,ht, light, dark)=
    image(for i = 0 upto wd-1:
        for j = 0 upto ht-1:
            fill unitsquare shifted (i,j) withcolor if odd(i+j): dark else: light fi;
        endfor
    endfor)
    enddef;

% basic shades
shade0=0.3white;
shade1=0.5white;
shade2=0.8white;

% Geometry of shadow: M gradations to penumbra, and each gradation has N offset copies of shadow
M:=10;
N:=36;
shadow_ysc:=1.8;    % stretched y-wise this much
shadow_ysc.blur:=0.15;
shadow_slant:=0.21; % slanted by this ratio
shadow_slant.blur:=0.05;

% set up picture and extract paths
TeX0=btex \bf\TeX etex;
_i:=1;
for $ within TeX0:
    p[_i]=pathpart glyph (textpart $) of (fontpart $) scaled 1/100 shifted llcorner $;
    _i:=_i+1;
endfor

% paths overlap, so extract subpaths to join back together
p1trim0=subpath (-1,length(p1)-2) of p1 cutbefore  p2 cutafter  p2;
p2trim0=subpath (1.1,length(p2)-.1) of p2 cutbefore p3 cutafter (subpath (-1,0) of p1);
p2trim1=subpath (1.1,length(p2)-.1) of p2 cutbefore p1 cutafter p3;
p3trim0=p3 cutafter subpath(1,2) of p2;
p3trim1=(subpath (2,infinity) of cuttings) cutbefore subpath(0,-1) of p2;
p0trim0=p1trim0--p2trim1--p3trim1--p3trim0--p2trim0--cycle;
p0=p0trim0 shifted -llcorner p0trim0 scaled 0.13 shifted (0.12,0.06);

% set up affine transforms for 4 different planes
% T0 maps to top of box and T1 maps to floating text
origin transformed T0=origin transformed T1=origin;
right transformed T0=right transformed T1=5cm*dir(-10);
up transformed T0=3cm*dir(20);
up transformed T1=5cm*up;
% T2 maps to front of box
(0,1) transformed T2=(0,-1) transformed T0;
(1,1) transformed T2=(1,-1) transformed T0;
(0,1) transformed T2=origin transformed T2+.5((up transformed T1)-(origin transformed T1));
% T3 maps to right of box
(0,1) transformed T3=(4,3) transformed T0;
(1,1) transformed T3=(4,2) transformed T0;
(0,1) transformed T3=origin transformed T3+(up transformed T2)-(origin transformed T2);

beginfig(1)
    % first draw grid without shadow
    draw gridpic(4,4,shade2,shade1) shifted (0,-1) transformed T0;
    % then successively darker parts of grid (multiple copies, as penumbra is blurred)
    for j = M-1 downto 1:
        checks0:=gridpic(4,4,(j/M)[shade1,shade2],(j/M)[shade0,shade1]) shifted (0,-1) transformed T0;
        for i = 0 upto N-1:
            checks1:=checks0;
            clip checks1 to
                p0 yscaled (shadow_ysc+shadow_ysc.blur*(j/M)*cosd(i/N*360))
                    slanted (shadow_slant+shadow_slant.blur*(j/M)*sind(i/N*360))
                    transformed T0;
            draw checks1;
        endfor
    endfor
    % finally, the actual shadow
    checks1:=gridpic(4,4,shade1,shade0) shifted (0,-1) transformed T0;
    clip checks1 to (p0 yscaled shadow_ysc slanted shadow_slant transformed T0);
    draw checks1;
    % floating text, repeated a few times to fake 3D
    for i = 3/4 step -1/16 until 0:
        fill p0 transformed T1 shifted ((0,i/10) transformed T0)  withcolor (i if i>0:+.2 fi)[(.8,.9,1),shade0];
    endfor
    % front and side of box
    draw gridpic(4,1,.3[shade2,white],.3[shade1,white]) transformed T2;
    draw gridpic(4,1,shade1,shade0) transformed T3;
    % identify three areas all of color shade1, even if they don't look it
    z0=(2.5,1.5) transformed T0;
    z1=(3.5,-0.5) transformed T0;
    z2=(2.5,0.5) transformed T3;
    for i = 0 upto 2:
        draw fullcircle scaled 6mm shifted z[i] withcolor shade2;
    endfor
%   uncomment this if you are not convinced:
%   fill z0..tension 4..z1..tension 4..z2..tension 4..cycle withcolor shade1;
endfig;

bye

enter image description here

share|improve this answer
add comment

Here is an autostereogram coded in TeX. If you've never heard of autostereograms, be aware that seeing anything other than random glyphs may require some practice on your part :)

Reference: Reinhard Fößmeier's Tugboat article.

enter image description here

\pdfpagewidth=300 true mm
\hsize= 250 true mm
\pdfpageheight=350 true mm
\newcount\alt
\def\Pixel#1{%
    \def\Head##1##2!{##1}%
    \def\Tail##1##2!{##2}%
    \edef\A{\expandafter\Head\Pat!}%
    \edef\Rest{\expandafter\Tail\Pat!}%
    \edef\T{\Rest}%
    \alt=#1
    \loop\ifnum\alt>0
    \edef\A{\expandafter\Head\T!}%
    \edef\T{\expandafter\Tail\T!}%
    \advance\alt -1%
    \repeat%
    \edef\Pat{\Rest\A}%
    \A%
}
\def\Line#1{%
    \if #1;\vskip0pt\else%
        \Pixel#1\Pixel#1%
        \expandafter\Line%
    \fi
}
\def\Dline#1;{%
    \edef\Pat{\StartPattern}%
    \Line#1;\Line#1;%
}
\edef\StartPattern{A-Cel'+MX-/()pd=}
\tt
\Dline 0000000000000000000000000000000000000000000000000000000;
\Dline 0000000000000000000000000000000000000000000000000000000;
\Dline 0000000000000000000001111111111111000000000000000000000;
\Dline 0000000000000000011111111111111111111100000000000000000;
\Dline 0000000000000011111111111111111111111111100000000000000;
\Dline 0000000000001111111111111111111111111111111000000000000;
\Dline 0000000000011111111000001111111100000111111100000000000;
\Dline 0000000000111111110000000111111000000011111110000000000;
\Dline 0000000001111111110000000111111000000011111111000000000;
\Dline 0000000011111111111000001111111100000111111111100000000;
\Dline 0000000011111111111111111111111111111111111111100000000;
\Dline 0000000011111101111111111111111111111111011111100000000;
\Dline 0000000001111100111111111111111111111110011111000000000;
\Dline 0000000000111110011111111111111111111100111110000000000;
\Dline 0000000000011111100111111111111111110011111100000000000;
\Dline 0000000000001111111100011111111110001111111000000000000;
\Dline 0000000000000011111111100000000001111111100000000000000;
\Dline 0000000000000000011111111111111111111100000000000000000;
\Dline 0000000000000000000001111111111111000000000000000000000;
\Dline 0000000000000000000000000000000000000000000000000000000;
\Dline 0000000000000000000000000000000000000000000000000000000;
\bye
share|improve this answer
    
I am losing the left side of the image, as there is depth detail near the edge. Some L/R padding (manual or auto) will probably improve things. –  Andrew Kepert Dec 30 '13 at 6:13
    
@AndrewKepert You're right. See my edit. –  Jubobs Dec 30 '13 at 10:12
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.