2011-12-13 14 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オブジェクトでも同じことが起こっています。 –

+0

私は@userが正しいと思います。オブジェクトを前面に再描画してみてください。オブジェクトがそれ以下のものを検出していない場合は、おそらくブレンド機能をスキップし、白い背景はカウントされません。 –

+0

オブジェクトを正面に再描画するとどういう意味ですか?これは問題を説明するための非常に簡単な例です。元のアプリには、回転する回転イメージとテキストがいくつかあり、すべてのオブジェクトの位置が50msごとに変更されていたため、常に再描画されていました。 –

答えて

4

FireMonkey(現在のところ)は、半透明のオブジェクトを3Dでレンダリングすることはサポートしていません。

FireMonkeyのが唯一の(例えばOpacityプロパティから、または、それらのテクスチャのいずれか、半透明のPNG画像)の半透明オブジェクトのをブレンドをサポートしていますが、一人でblendingがで右3Dでそれを取得するのに十分ではありませんa Z-Buffer(これはFMXとほとんどの3Dアプリケーションが使用しているものです)。

技術的な説明については、Transparency sortingについて読むことができます。この記事はOpenGLについて書かれていますが、DirectXにも適用されます。

正しいレンダリングを得るには、半透明のオブジェクトをカメラの視点からバックツーフロントで並べ替える必要があります。

あなたが問題を回避するために、この記事で詳細およびいくつかのコードを取得することができます:

Rendering semi-transparent object in FireMonkey

をしかし、それだけでこの問題を回避するだろうに注意してください。

これは、レンダリングに依存するため、FireMonkeyシーングラフで処理するのが理想です。そうしないと、シーングラフ構造を変更する必要があります。これにはさまざまな副作用があります。あなたが同じシーンを見ている複数のカメラを持っている場合は問題があります。なしが存在する

Triple Overlap example

いる:

また、仕分けのアプローチは、唯一のように、交差しない、そしてそのためにあなたはトリプルオーバーラップを持たない凸のオブジェクトを操作します正しいソート(要素のどれも他の要素の前にありません)。

0

すでにわかっているように、透明なオブジェクトを前後に描画する必要があります。

透明なオブジェクトを描画する場合、そのオブジェクトは描画され、その背景にあるピクセルとブレンドされます。

これは、前から描画するときに発生します。
赤いイメージを描画し、白い背景とブレンドします。純粋な赤色ではなく、ピンク色で、白い背景と混ざり合っています。次に、緑のイメージを描画し、既に描画された白い背景と赤のイメージとブレンドされます。最後に、すでに描画されたオブジェクトとブレンドされた青いイメージを描画します。

しかし、ここでは前から後に描画します:
赤い面を最初に描画します。それは赤の代わりにピンクであるため、あなたが見ることができる白い背景とブレンドされます。今、緑色の平面を描画します。それは白い背景とブレンドされ、あなたは色で伝えることができます、それは純粋な、深い、緑ではありません。しかし、レンダラーは部品が赤い面の後ろにあることを知るので、その部分を描画しません。しかし、あなたは考えます:赤い平面は透明です、レンダラーはその赤い平面の後ろに描画する必要があります!いいえ、レンダラはzバッファ/デプスバッファ内のピクセルの深度/ zオーダーを追跡しているだけで、そのピクセルが透過かどうかはわかりません。同じ物語が青い平面に行き、他のオブジェクトによって隠されていない部分だけが描かれます。

あなたが話すこの深度バッファは何ですか?
デプスバッファには、すべてのピクセルの深度が格納されます。 azが1の2,2にピクセルを描画すると、2,2のデプスバッファが値1で更新されます。次に、3のazを持つ1,2から3,2の線を描画すると、レンダラーデプスバッファが> = 3の値を持つピクセルだけを描画します。したがって、ピクセル1,2が描画されます(1,2のデプスバッファが3に設定されます)。デプスバッファは、そのピクセルがすでに深度の低いもの(1対3)で描画されていることを示すため、ピクセル2,2は描画されません。ピクセル3,2が描画され、3,2のデプスバッファは3に設定されます。
デプスバッファは、すべてのピクセルのzオーダーを追跡して、そのピクセルを遠く離れた。

透明なオブジェクトを正しい方法で描画する場合は、this answerを参照してください。その答えから

抜粋:

  • まず不透明なオブジェクトを描画します。
  • デプスバッファ書き込みを無効にします(デプスバッファは更新されません)。ただし、デプスバッファチェックを有効にしてください。
  • 透明オブジェクトを描画します。デプスバッファは更新されないので、透明なオブジェクトが互いに見えにくいという問題はありません。デプスバッファチェックが有効なので、不透明なオブジェクトの背後に描画しません。

FireMonkeyがデプスバッファ書き込みを無効にすることをサポートしているかどうかわかりませんが、自分で見つけなければなりません。

関連する問題