Engee 文档

透明度

该页面正在翻译中。

要使绘图透明,您需要向其添加alpha值 颜色颜色表. </无翻译>

using CairoMakie
using FileIO

# color
fig, ax, p = image(0..11, -1..11, rotr90(FileIO.load(Makie.assetpath("cow.png"))))
scatter!(ax, 1:10,fill(10, 10), markersize = 40, color = :red)
scatter!(ax, 1:10, fill(9, 10), markersize = 40, color = (:red, 0.5))
scatter!(ax, 1:10, fill(8, 10), markersize = 40, color = RGBf(0.8, 0.6, 0.1))
scatter!(ax, 1:10, fill(7, 10), markersize = 40, color = RGBAf(0.8, 0.6, 0.1, 0.5))

# colormap
scatter!(ax, 1:10, fill(5, 10), markersize = 40, color = 1:10, colormap = :viridis)
scatter!(ax, 1:10, fill(4, 10), markersize = 40, color = 1:10, colormap = (:viridis, 0.5),)
scatter!(ax, 1:10, fill(3, 10), markersize = 40, color = 1:10, colormap = [:red, :orange],)
scatter!(ax, 1:10, fill(2, 10), markersize = 40, color = 1:10, colormap = [(:red, 0.5), (:orange, 0.5)])
cm = [RGBf(x^2, 1 - x^2, 0.2) for x in range(0, 1, length=100)]
scatter!(ax, 1:10, fill(1, 10), markersize = 40, color = 1:10, colormap = cm)
cm = [RGBAf(x^2, 1 - x^2, 0.2, 0.5) for x in range(0, 1, length=100)]
scatter!(ax, 1:10, fill(0, 10), markersize = 40, color = 1:10, colormap = cm)
fig
8dc65f7

透明度问题

从两个重叠的透明对象生成的颜色取决于它们的顺序。 例如,考虑具有相同透明度的红色和蓝色标记。 如果蓝色标记在前面,我们期望在它们重叠的地方有更多的蓝色。 如果红色的在前面,我们期望更多的红色。 </无翻译>

using CairoMakie
scene = Scene(size = (400, 275))
campixel!(scene)
scatter!(
    scene, [100, 200, 300], [100, 100, 100],
    color = [RGBAf(1,0,0,0.5), RGBAf(0,0,1,0.5), RGBAf(1,0,0,0.5)],
    markersize=200
)
scatter!(scene, Point2f(150, 175), color = (:green, 0.5), markersize=200)
p = scatter!(scene, Point2f(250, 175), color = (:green, 0.5), markersize=200)
translate!(p, 0, 0, -1)
scene
7f4fd72

上图在透明度方面遵循三个规则:

  1. 如果两个图处于不同的z水平,则具有较高水平的图将位于较低z水平的前面。 (右边的绿色圆圈在所有其他地块的后面。)

  2. 同一z级绘图的绘制顺序与其创建顺序相匹配。 (红色和蓝色圆圈在左绿色圆圈后面。)

  3. 绘图元素按顺序绘制。 (左边的红圈在中间的蓝圈后面,在右边的红圈后面。)

第一条规则遵循图的显式排序。 它只能在2D中完成,因为绘图可以在3D中具有可变的深度。第二和第三条规则适用于这两种情况。 然而,它们会经常在3D中生成错误的结果。例如,两个平面旋转以具有不同的深度值: </无翻译>

using CairoMakie
fig = Figure()
ax = LScene(fig[1, 1], show_axis=false)
p1 = mesh!(ax, Rect2f(-1.5, -1, 3, 3), color = (:red, 0.5), shading = NoShading)
p2 = mesh!(ax, Rect2f(-1.5, -2, 3, 3), color = (:blue, 0.5), shading = NoShading)
rotate!(p1, Vec3f(0, 1, 0), 0.1)
rotate!(p2, Vec3f(0, 1, 0), -0.1)
fig
6ddc2c5

</无翻译>

using GLMakie
fig = Figure()
ax = LScene(fig[1, 1], show_axis=false)
p1 = mesh!(ax, Rect2f(-1.5, -1, 3, 3), color = (:red, 0.5), shading = NoShading)
p2 = mesh!(ax, Rect2f(-1.5, -2, 3, 3), color = (:blue, 0.5), shading = NoShading)
rotate!(p1, Vec3f(0, 1, 0), 0.1)
rotate!(p2, Vec3f(0, 1, 0), -0.1)
fig
c44708d

两个后端处理这个错误。 CairoMakie似乎忽略了深度,只是按照绘图顺序绘制平面。 这并不完全正确-CairoMakie确实在每个情节上考虑深度,在某些情况下在每个元素的基础上考虑深度(例如3d网格中的三角形)。 但它不能处理每像素级别的深度。

另一方面,GLMakie可以处理每像素级别的深度,如上所示的正确顺序所示。 这里透明度的问题是,应用于像素的颜色顺序不是先验已知的。 GLMakie将首先绘制红色平面,并记录每个像素的深度值。 然后它会绘制蓝色平面,如果它在另一个前面。 准确解决这个问题需要收集每个像素的颜色和深度值,对它们进行排序,然后按顺序混合它们。 这将是非常昂贵的,因此很少做。

订单独立透明度

GLMakie实现了混合透明颜色的近似方案-https://jcgt.org/published/0002/02/09/[订单独立透明度](OIT)。 而不是使用通常的顺序依赖混合 alpha*color+(1-alpha)*background_color 它使用基于深度和alpha的权重的加权和。 您可以通过设置打开OIT 透明度=真 对于给定的情节。 </无翻译>

using GLMakie
fig = Figure()
ax = LScene(fig[1, 1], show_axis=false)
p1 = mesh!(ax, Rect2f(-2, -2, 4, 4), color = (:red, 0.5), shading = NoShading, transparency = true)
p2 = mesh!(ax, Rect2f(-2, -2, 4, 4), color = (:blue, 0.5), shading = NoShading, transparency = true)
p3 = mesh!(ax, Rect2f(-2, -2, 4, 4), color = (:red, 0.5), shading = NoShading, transparency = true)
for (dz, p) in zip((-1, 0, 1), (p1, p2, p3))
    translate!(p, 0, 0, dz)
end
fig
8cca7b2

作为一个近似的方案,OIT有一些优点和缺点。 OIT有两个显着的缺点:

  1. 混合总是发生-即使完全不透明的颜色(alpha=1)应该隐藏另一个。

  2. 混合不是尖锐的-当具有相同alpha值的两种颜色以相似的深度值混合时,它们的输出颜色将相似。

</无翻译>

using GLMakie
fig = Figure(size = (800, 400))
ax1 = LScene(fig[1, 1], show_axis=false)
p1 = mesh!(ax1, Rect2f(-2, -2, 4, 4), color = :red, shading = NoShading, transparency = true)
p2 = mesh!(ax1, Rect2f(-2, -2, 4, 4), color = :blue, shading = NoShading, transparency = true)
p3 = mesh!(ax1, Rect2f(-2, -2, 4, 4), color = :red, shading = NoShading, transparency = true)
for (dz, p) in zip((-1, 0, 1), (p1, p2, p3))
    translate!(p, 0, 0, dz)
end

ax2 = LScene(fig[1, 2], show_axis=false)
p1 = mesh!(ax2, Rect2f(-1.5, -1, 3, 3), color = (:red, 0.5), shading = NoShading, transparency=true)
p2 = mesh!(ax2, Rect2f(-1.5, -2, 3, 3), color = (:blue, 0.5), shading = NoShading, transparency=true)
rotate!(p1, Vec3f(0, 1, 0), 0.1)
rotate!(p2, Vec3f(0, 1, 0), -0.1)
fig
3e95688

请注意,您可以混合不透明 透明度=错误 具有透明OIT图的图没有问题。 因此,第一个问题并不是真正不透明的地块的问题,而是接近不透明的地块。

你可能遇到的另一个问题是你的情节的一部分变成黑色或白色。 这是在OIT计算期间浮点数变为无限的结果,因为在相机附近添加了大量透明颜色。 你可以用两种方式解决这个问题:

  1. 移动 附近 裁剪平面更接近相机。 对于一个 ax::LScene 这可以通过调整来完成 斧头场景。camera_controls.近[] 接近0和调用 update_cam!(斧头。场景,斧头。场景。camera_controls).

  2. 减少开支 格玛基。透明_weight_scale[] 其控制赋予透明颜色的最大权重。 默认值为 1000f0.

调整后者也可能有助于清晰度。