安德鲁·史黛西指出罗塞塔密码条目“画一个球体”尚无 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。
这使用了\pgfdeclarefunctionalshading
percusse 答案中的命令。当然,我们只给出了每个向量的两个元素,所以我们需要先计算第三个元素。
由于某种原因,圆圈的阴影需要为 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}