如何绘制阴影球体?

如何绘制阴影球体?

安德鲁·史黛西指出罗塞塔密码条目“画一个球体”尚无 TikZ 条目。

有没有办法使用 TikZ 绘制“正确”着色的球体?ball着色似乎是一个显而易见的选择,但它使用圆形高光,这与现实中看起来不一样。那么:有没有办法制作一个类似于白色、哑光(即无光泽)球体的球体,该球体由单个白色光源照亮?

我认为这主要需要获得非圆形、正确定向的高光。Yori 和 Altermundus 的答案都已经很好地使用了“更柔和”的高光,看起来更可信,但 Altermundus 的高光仍然是圆形的,而 Yoris 的高光是椭圆形的,我认为它的方向不正确。

比较一个带有阴影的圆圈ball使用 Perl 6 制作的示例

\documentclass{article}

\usepackage{tikz}

\begin{document}

\begin{minipage}{2.5cm}\centering
\scriptsize That's not a sphere.

\tikz{
    \fill [black] (-1,-1) rectangle (1,1);
    \shade [ball color=white] (0,0) circle [radius=1cm];
}
\end{minipage}%
%
\begin{minipage}{2.5cm}\centering
\scriptsize \emph{That's} a sphere.

\includegraphics[width=2cm]{Sphere-perl6.png}
\end{minipage}
\end{document}

答案1

我正在关注之前的帖子有没有办法调整 TikZ 中的球阴影?,特别是 Stefan Kottwitz 的回答。他展示了如何使用\pgfdeclareradialshading来更改径向阴影。更改径向的参数并添加一些剪辑,我可以生成以下内容:

这个球体够大吗?也许再做一些调整就能得到更好的结果。实现此效果的代码是:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\makeatletter
\pgfdeclareradialshading[tikz@ball]{ball}{\pgfqpoint{-20bp}{20bp}}{%
 color(0bp)=(tikz@ball!0!white);
 color(17bp)=(tikz@ball!0!white);
 color(21bp)=(tikz@ball!70!black);
 color(25bp)=(black!70);
 color(30bp)=(black!70)}
\makeatother

\begin{tikzpicture}
    \fill [black] (-1,-1) rectangle (1,1);
    \begin{scope}
        \clip (0,0) circle (1);
        \shade [ball color=white] (-0.1,0) ellipse (1.2 and 1);
    \end{scope}
\end{tikzpicture}

\end{document}

或者,使用更椭圆形的阴影,可以得到这样的结果:

对此的解释是:

\documentclass{article}

\usepackage{tikz}

\begin{document}

\makeatletter
\pgfdeclareradialshading[tikz@ball]{ball}{\pgfqpoint{0bp}{0bp}}{%
 color(0bp)=(tikz@ball!0!white);
 color(10bp)=(tikz@ball!0!white);
 color(15bp)=(tikz@ball!70!black);
 color(20bp)=(black!70);
 color(30bp)=(black!70)}
\makeatother

\begin{tikzpicture}

    \fill [black] (-1,-1) rectangle (1,1);

    \begin{scope}
        \clip (0,0) circle (1);
        \draw [fill=black!70] (0, 0) circle (1);
        \begin{scope}[transform canvas={rotate=45}]
        \shade [ball color=white] (0,0.5) ellipse (1.8 and 1.6);
        \end{scope}
    \end{scope}

\end{tikzpicture}

\end{document}

这是一个试验和摆弄参数的问题,以找到最适合您的效果(从上面的讨论来看,这似乎是相当主观的事情)。请注意,您需要transform canvas={rotate=45}在内部范围内指定,而不是rotate=45因为后者不会旋转填充。

答案2

如果光源距离很远,则每个点的强度是位置向量和光源向量(在 R 3中)的点积,阈值为 0。

这使用了\pgfdeclarefunctionalshadingpercusse 答案中的命令。当然,我们只给出了每个向量的两个元素,所以我们需要先计算第三个元素。

由于某种原因,圆圈的阴影需要为 50bp x 50bp,否则不起作用。

\documentclass[border=5mm]{standalone}
\usepackage{tikz}

\pgfdeclarefunctionalshading{sphere}{\pgfpoint{-25bp}{-25bp}}{\pgfpoint{25bp}{25bp}}{}{
%% calculate unit coordinates
25 div exch
25 div exch
%% copy stack
2 copy 
%% compute -z^2 of the current position 
dup mul exch
dup mul add
1.0 sub
%% and the -z^2 of the light source 
0.3 dup mul
-0.5 dup mul add
1.0 sub
%% now their sqrt product
mul abs sqrt
%% and the sum product of the rest
exch 0.3 mul add
exch -0.5 mul add
%% max(dotprod,0)
dup abs add 2.0 div 
%% matte-ify
0.6 mul 0.4 add
%% currently there is just one number in the stack.
%% we need three corresponding to the RGB values
dup
0.4
}

\begin{document}
\begin{tikzpicture}
  \shade[shading=sphere] (0,0) circle [radius=5cm];
\end{tikzpicture}
\end{document}

领域

答案3

为了提高 PS 的性能,我修改了 PGF 手册中给出的功能阴影。我确信 PSTricks 及其步兵在这类绘图方面表现得更好,但 Acrobat 和 Sumatra 的渲染效果相当令人印象深刻。

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\pgfdeclarefunctionalshading{eightball}{\pgfpointorigin}{\pgfpoint{100bp}{100bp}}{}{
% Compute distance difference (horizontally weighted twice). (50bp,50bp) is the center
65 sub dup mul exch               %Change the coordinate to move vertically
40 sub dup mul 0.5 mul add sqrt   %Change the coordinate to move horizontally
% In MATLAB notation : d=distance diff
% x=1.003^(-d^2)
dup mul neg 1.003 exch exp
% x is the only variable in the stack now but we need 3 values at the top of the stack
% so we duplicate these values putting new values in the stack.
dup % Duplicates with the current value and pushes the stack down (value of green)
dup % Duplicates with the current value and pushes the stack down (value of blue)
}

\begin{document}
\begin{tikzpicture}
\shade[shading=eightball] (0,0) circle (5cm);
\end{tikzpicture}
\end{document}

你可以尝试用从黑色到白色的dup间隔值替换最后的命令[0.0,1.0]。例如,作为一个色盲,如果我0.3,0.2分别设置这些值,我的大脑就会停止渲染并显示一个痛苦的错误代码。

在此处输入图片描述

答案4

或许是这样的

\documentclass[11pt]{scrartcl}
\usepackage{tikz}
\begin{document}

\pgfdeclareradialshading{ballshading}{\pgfpoint{-10bp}{10bp}}
 {color(0bp)=(gray!40!white); 
 color(9bp)=(gray!75!white);
 color(18bp)=(gray!70!black); 
 color(25bp)=(gray!50!black); 
 color(50bp)=(black)}

\begin{pgfpicture}
  \pgfpathcircle{\pgfpoint{0cm}{0cm}}{2cm}
  \pgfshadepath{ballshading}{20}
  \pgfusepath{}
\end{pgfpicture}  

\end{document}

在此处输入图片描述

相关内容