透明Image3D有时是不透明的

我用3个半透明tImage3D创建了一个FireMonkey应用程序。 这是代码和屏幕。 一切似乎都很好。

procedure TForm1.Form3DCreate(Sender: TObject);

// create a new semi-transparent timage3d
// object with color and Z position.
procedure NewImage ( const nColor : tColor;
                     const nZ     : integer );
begin
  // create the image
  with tImage3D . Create ( self ) do
    begin
      // put it on the screen
      Parent := self;
      // set the size
      Width := 10;
      Height := 10;
      // set the image to a single pixel.
      Bitmap . Width := 1;
      Bitmap . Height := 1;
      // set the Alpha to $80 to make it
      // semi-transparent
      Bitmap . Pixels [ 0, 0 ] := $80000000 + nColor;
      // set the z position
      Position . Z := nZ;
    end;
end;

begin
  NewImage ( claRed,   +10 );
  NewImage ( claGreen,   0 );
  NewImage ( claBlue,  -10 );
end;

一切都很好

现在扭转顺序。 现在它们是不透明的。

begin
  NewImage ( claRed,   -10 );
  NewImage ( claGreen,   0 );
  NewImage ( claBlue,  +10 );
end;

现在它们是不透明的

我错过了什么?


FireMonkey(截至目前)不支持在3D中渲染半透明对象。

FireMonkey只支持半透明对象的混合 (通过不透明属性或由于它们的纹理,例如半透明PNG图像),但单独混合并不足以使用Z-Buffer(3D是FMX和大多数3D应用程序正在使用的)。

有关技术说明,您可以阅读有关透明度排序,文章是关于OpenGL,但也适用于DirectX。

因此,为了获得正确的渲染效果,您需要从相机的角度来反向排序您的半透明对象

你可以在这篇文章中获得更多的细节和一些代码来解决这个问题:

在FireMonkey中渲染半透明对象

但请记住它只是一个解决方法

理想情况下,这应该由FireMonkey场景图来处理,因为它是依赖于渲染的,否则,最终不得不改变场景图结构,这会产生各种其他副作用,并且如果您有问题不止一台摄像机正在看同一场景。

此外,排序方法只适用于不相交的凸对象,并且您没有三重交叠,如下所示:

对此没有正确的排序(没有任何元素在其他人面前)。


正如您已经发现的,您必须从后到前绘制透明物体。

绘制透明对象时,绘制该对象,并与其后面的像素进行混合。

所以这种情况发生在你从前到后画的时候:
您绘制红色图像,它与白色背景混合。 你可以通过“粉红色”而不是纯红色来判断它是否与白色背景混合。 然后绘制绿色图像,将其与已绘制的白色背景和红色图像混合。 最后,您绘制蓝色图像,该图像与已绘制的对象混合。

但现在我们从前到后绘制:
我们先画红色的飞机。 它与您可以看到的白色背景相融合,因为它是粉红色而不是红色。 现在我们画绿色的飞机。 它与白色背景融为一体,你可以通过颜色来判断,它不是纯粹,深沉,绿色。 但是,渲染者看到一部分落在红色的飞机后面,所以它不会吸引那部分。 但是,你认为:红色的飞机是透明的,渲染者应该在这架红色飞机后面画画! 嗯,渲染器只跟踪z缓冲区/深度缓冲区中像素的深度/ z顺序,它不知道该像素是否透明。 同样的故事也适用于蓝色飞机,只有没有被其他物体遮挡的部分才会被绘制出来。

你所说的深度缓冲区是什么?
在深度缓冲区中存储每个像素的深度。 当您在az处绘制一个像素为2,2的az时,2,2中的深度缓冲区将更新为值1.现在,当您绘制一条线从1,2到3,2且az为3时,渲染器将仅绘制深度缓冲区具有> = 3的值的像素。因此,绘制像素1,2(并且1,2的深度缓冲区设置为3)。 未绘制像素2,2,因为深度缓冲区指示该像素已经以较小的深度绘制(1 vs 3)。 像素3,2被绘制并且深度缓冲器3,2被设置为3。
因此,深度缓冲区用于跟踪每个像素的z阶,以防止用更远的像素覆盖该像素。

如果您想以正确的方式绘制透明物体,请参阅此答案。

摘自该答案:

  • 首先绘制不透明的物体。
  • 禁用深度缓冲区写入(因此深度缓冲区不会更新),但保持启用深度缓冲区检查。
  • 绘制透明物体。 由于深度缓冲区没有更新,因此不存在透明对象互相遮挡的问题。 由于启用了深度缓冲区检查,因此不会在不透明对象后面绘制。
  • 我不知道FireMonkey是否支持禁用深度缓冲写入,你必须找出你自己。

    链接地址: http://www.djcxy.com/p/56759.html

    上一篇: transparent Image3D is sometimes opaque

    下一篇: How to add an extra project into existing Android operating system source?