RenderTarget2D.GetTexture()は同じアドレスを返す
RenderTarget2D.GetTexture()した結果を配列や二つの変数に代入し、あとからそのRenderTarget2Dをいじくり回すと両者が同じになるということについてです。
何のこっちゃさっぱりって人は、こちらのサンプルをどうぞ。XNA3.0で作成しています。
操作方法
左シフト->レンダリングターゲットからテクスチャを取得し左側のテクスチャに代入する。
右シフト->レンダリングターゲットからテクスチャを取得し右側のテクスチャに代入する。
そうするとソース上では片方しか描き換えてないのに、 両方書き換わってしまう。
私は最初これと同じようなことをしていて、この現象に出合い混乱して乱数クラスが狂ったのかと思いました。でもデバッガで追ってくと そうじゃなかったですね。ちゃんと乱数になってましたし、代入してるのも変数一つでした。で、ふと思いついたのが「ポインタ」って言葉。もしGetTexture()で取得できるオブジェクトのアドレスが同じならつじつまが通る…!
確かめてみようと思ってunsafeコード書いてみましたが、どうやら値型のアドレスは取得できても参照型のアドレスは取得できないようで、断念。
で、どうするか。下のような感じでディープコピーしてやればOKです。
GraphicsDevice.SetRenderTarget(0, null); Texture2D newTex = new Texture2D(GraphicsDevice, tex1.Width, tex1.Height); Color[] data = new Color[tex1.Width * tex1.Height]; target.GetTexture().GetData(data); newTex.SetData(data); tex1 = newTex;
ただひとつ問題なのがこの記事で検証されているようにXBOX360上ではGetData()/SetData()がパフォーマンスにかなり影響を与えるようです。特にGetData()が。今のところこれに対する対策は見つかってません…。描画処理をGPU上で全部やって最終的にテクスチャをもらうということぐらいしか思いつきません。ただそれだとfxファイルを書かなければならないですし、SpriteBatchなどで複雑な描画をしていた場合はとGPUには不向きかと。
うが~~~~!!!
XBOXでゲーム作りたいです…。
2009-12-16 01:18:49追記。
簡単な話でしたね。GetTexture()する数だけRenderTarget2Dを作ればいいんですね。
なぜ気がつかなかった!???
疲れてきてるな流石に…