gnuplot:如何避免视角相关的半透明 3D 表面?

gnuplot: how to avoid viewing angle dependent semitransparent 3D surfaces?

我偶然发现了以下内容。 如果我绘制,例如使用 pm3d 的立方体并将边定义为半透明,如果我将立方体旋转 90 度的倍数,我希望立方体看起来是一样的。 然而,显然取决于视角,特定表面看起来比其他表面更亮或更暗。在下面的示例中,30 度和 120 度的视图有 3 种不同的红色阴影,而 210 度和 300 度的视图只有 2 种红色阴影。没有pm3d lighting涉及。

问题: 这怎么解释呢?如何避免这种情况?我对立方体的定义有问题吗? 我是否遗漏了 help pm3dhelp pm3d algorithmhelp pm3d color_assignment 下的文档中的任何内容?我使用的是太旧的 gnuplot 版本 (5.2.8) 还是“错误的”终端 (wxt)?

代码:

### semitransparent 3D surfaces
reset session

$Cube <<EOD
0 0 0
0 0 1
0 1 1
0 1 0
0 0 0

1 0 0
1 0 1
1 1 1
1 1 0
1 0 0

0 0 0
1 0 0
1 1 0
0 1 0
0 0 0

0 0 1
1 0 1
1 1 1
0 1 1
0 0 1
EOD

set view equal xyz
set cbrange [0.9:1]
set palette defined (1 'red')
set pm3d depthorder hidden3d
set pm3d implicit
unset hidden3d
unset label
unset tics
unset border
unset key
unset colorbox

set multiplot layout 2,3
    a=75
    b=30
    r=1.3
    set title sprintf("opaque view: %d, %d",a,b)
    set view a,b,r
    set style fill transparent solid 1
    splot $Cube u 1:2:3:(1) w l lw 0.5 lc "black"
    
    set style fill transparent solid 0.3
    do for [i=30:300:90] {
        set title sprintf("transparent view: %d, %d",a,i)
        set view a,i
        replot
    }
unset multiplot
### end of code

结果:

这里发生了很多事情

  1. 最初我认为您所看到的部分证据表明,无论您使用的是哪个终端,图形渲染的合成操作都是不可传递的。但是我认为没有这个就可以解释大部分或所有的影响。

      (background ∘ 0.3red) ∘ 0.3red  ?=?  background ∘ (0.3red ∘ 0.3red)
    
  2. 一个关键是你的“立方体”并不是真正的立方体;它缺少 2 张面孔。如果将它们绘制为多边形,视角的差异效果会更加明显:

    unset pm3d
    splot $Cube u 1:2:3 w polygons
    
  3. 因为您使用的是 with pm3d,程序试图将顶点解释为定义曲面的一组扫描线。这真的行不通。我不完全确定最终结果是什么,但我怀疑某些区域被绘制了两次。您可以通过使用

    再次绘制来了解这里出了什么问题
     set pm3d interpolate 2,2
    

如果添加立方体缺失的两个面并绘制面 with polygons,效果将完全消失。

set view equal xyz
unset hidden3d
unset tics
unset border
unset key

set multiplot layout 2,3
    a=75
    b=30
    r=1.3
    set title sprintf("opaque view: %d, %d",a,b)
    set view a,b,r
    set style fill transparent solid 1
    set pm3d border lw 0.5 lc "black"
    splot $Cube u 1:2:3 w polygons fc "red"
    
    set style fill transparent solid 0.3
    do for [i=30:300:90] {
        set title sprintf("transparent view: %d, %d",a,i)
        set view a,i
        replot
    }
unset multiplot