2011-12-13 80 views
7

我使用3個半透明tImage3D創建FireMonkey應用程序。 這是代碼和屏幕。一切似乎都很好。Firemonkey半透明Image3D有時是不透明的

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; 

All is well

現在顛倒順序。現在它們是不透明的。

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

Now they are opaque

我缺少什麼?

+3

顯然,一個對象對前面創建的對象只是半透明的。如果那有意義的話。紅色框呈現爲粉紅色,因爲儘管可以看到白色背景,但您無法通過它看到綠色或藍色框。通過綠色框,你可以看到白色背景和紅色框,但不是藍色框。我也有同樣的事情與text3d對象發生。 – 2011-12-14 00:22:12

回答

4

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

FireMonkey只支持混合半透明物體(通過,因爲他們的紋理的透明度財產或者,例如半透明PNG圖像),但blending是不夠用得到它的權利在3D一個Z-Buffer(這是什麼FMX,和大多數3D應用程序正在使用)。

有關技術說明,您可以閱讀有關Transparency sorting,文章是關於OpenGL,但也適用於DirectX。

因此,要獲得正確的渲染,您需要從攝像機的角度後面到前面排列您的半透明對象。

你可以得到更多的細節和一些代碼在這個崗位要解決這個問題:

Rendering semi-transparent object in FireMonkey

但請記住,這將只是一個解決方法

理想情況下,這應該由FireMonkey場景圖處理,因爲它依賴於渲染,否則,最終不得不更改場景圖結構,該結構可能具有各種其他副作用,甚至更多如果您有多臺相機在同一場景中觀看,則會出現問題。

此外,排序方法將只能與不相交的凸對象的工作,和你沒有三重疊,如:

Triple Overlap example

對於那些不存在正確的排序(沒有任何元素在其他人面前)。

0

正如你已經發現你必須從後到前繪製透明物體。

繪製透明物體時,繪製物體並與其後面的像素混合。

所以這種情況發生在您從後到前繪製時:
您繪製紅色圖像,它與白色背景混合。你可以通過「粉紅色」而不是純紅色來判斷它是否與白色背景混合。然後繪製綠色圖像,將其與已繪製的白色背景和紅色圖像混合。最後,您繪製藍色圖像,該圖像與已繪製的對象混合。

但是現在我們從前到後繪製:
我們首先繪製紅色平面。它與您可以看到的白色背景相融合,因爲它是粉紅色而不是紅色。現在我們畫綠色的飛機。它與白色背景融爲一體,你可以通過顏色來判斷,它不是純粹,深沉,綠色。但是,渲染者看到一部分落在紅色的飛機後面,所以它不會吸引那部分。但是,你認爲:紅色的飛機是透明的,渲染者應該在這架紅色飛機後面畫畫!嗯,渲染器只跟蹤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階以防止用像素覆蓋該像素離得更遠。

如果要以正確的方式繪製透明物體,請參見this answer。從這個答案

摘錄:

  • 先畫不透明的物體。
  • 禁用深度緩衝區寫入(因此深度緩衝區未更新),但保持啓用深度緩衝區檢查。
  • 繪製透明物體。由於深度緩衝區沒有更新,因此不存在透明對象互相遮擋的問題。由於啓用了深度緩衝區檢查,因此不會在不透明對象後面繪製。

我不知道FireMonkey是否支持禁用深度緩衝區寫入,您必須找出自己。