トップページ > 過去ログ > 記事閲覧
画像バッファの扱いに関して
名前:crow 日時: 2007/03/10 11:58

お久しぶりでございます。 質問…というより要望なのですが、以下のふたつは可能でしょうか? ・前画面&裏画面を描画元のグラフィックハンドルとして扱うこと  (DrawGraph(0, 0, DX_SCREEN_BACK, FALSE); のように) ・アルファチャンネルに直接書き込むこと 前者の方は前フレームの画像を利用した モーションブラー等のエフェクトに使用したいと思っているので、 もし可能ならば実装していただけると大変助かります。 (現在は自前の裏画面のようなものを使って代用していますが、 これはさすがにメモリと描画処理が余計にかかります) 後者の方はかなり贅沢な機能だと思うので、 難しいようであれば気になさらないでください。 ちなみに用途は、 煙だけを縮小バッファに書き込んでその後拡大合成したり、 被写界深度の表現に使えたらいいかな、と思っています。 そこまでやるなら自分でグラフィックエンジン作れと言われそうですが…(汗) 今後は暇を見てDirectXの勉強もしてみたいです。

Page: 1 |

Re: 画像バッファの扱いに関して ( No.1 )
名前:管理人 日時:2007/03/12 15:14

 crowさんお久しぶりです、DXライブラリの管理人です。 > ・前画面&裏画面を描画元のグラフィックハンドルとして扱うこと >  (DrawGraph(0, 0, DX_SCREEN_BACK, FALSE); のように)  画面は通常の画像とは違い特別なものなので、グラフィックハンドル として扱うことは出来ません。(また、DirectX 的にもフレームバッファは テクスチャとして扱うことは出来ませんので、仮にDXライブラリに 手を加えてグラフィックハンドルとして扱えるようにしたとしても、 出来ることは ブレンドなし(DX_BLENDMODE_NOBLEND) 描画輝度設定変更なしの DrawGraph による単純転送くらいが関の山となります)  現在は MakeGraph で作成した描画可能テクスチャを裏画面として 扱っているのでしょうか? もしそうだとしますと、現時点ではそれが 最良の方法となります。(DirectX の機能として前述通りフレームバッファを テクスチャとして扱うことは出来ませんので、描画結果をテクスチャとして 使用する場合はメモリと描画処理が増えるのは仕方が無いようです) > ・アルファチャンネルに直接書き込むこと  現状のDXライブラリでは出来ません。  が、ちょっと面白そうなので色々試してみます。(現在少し忙しいので 一週間か二週間程時間が掛かってしまうかもしれません・・・出来たら このスレッドに書き込みます)  ただ、この機能をDXライブラリに実装したとしても、αチャンネル に直接書き込む処理が正常に動作するグラフィックチップは少し性能の 高いものになると思います。(チップセットのグラフィック機能を 使用しているメーカー製PCはデスクトップ、ノート共に 2003年以前 くらいに発売されたものは恐らく殆ど駄目だと思います・・・)
Re: 画像バッファの扱いに関して ( No.2 )
名前:crow 日時:2007/03/12 21:08

返答していただき、ありがとうございます。 > 画面は通常の画像とは違い特別なものなので、 > グラフィックハンドルとして扱うことは出来ません。 なるほど、これは無理だったんですね。 なんとなく「できそうかな?」と思ったんですが、素人考えでした^^; 現在は管理人さんの予想通りの方法を用いていますが、 今後もこのままいくことにします。 > 現状のDXライブラリでは出来ません。 > が、ちょっと面白そうなので色々試してみます。 おお、ありがとうございます。 急ぎの用ではないので、お暇ができた時で構いません。 現在3Dではライトブルームやフォグのような写実的な表現が流行っていますが、 私はなんとかそれを2Dの画面でやりたかったので、 DXライブラリのテクスチャに直接書き込む機能はとても役立っています。
Re: 画像バッファの扱いに関して ( No.3 )
名前:管理人 日時:2007/03/17 21:01

 crowさんどうも、DXライブラリの管理人です。  描画対象にすることが出来るαチャンネル付き画像を作成する機能と、 αチャンネル付き画像に描画するに当たって少し必要になる機能を 追加しました。  ただ、ちょっと曲者です。 http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe //VC用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe //BCC用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい)  このバージョンで追加した関数は以下の通りです。 // 描画可能なαチャンネル付き画像を作成するかどうかのフラグをセットする // SetDrawValidGraphCreateFlag 関数で描画可能画像を作成するように // 設定されていないと効果がない( TRUE:αチャンネル付き FALSE:αチャンネルなし ) int SetDrawValidAlphaChannelGraphCreateFlag( int Flag ); // SetDrawBlendMode 関数の第一引数に DX_BLENDMODE_NOBLEND を代入した際に // デフォルトでは第二引数は内部で255を指定したことになるが // その自動255化をしないかどうかを設定する // TRUE:しない(第二引数の値が使用される) // FALSE:する(第二引数の値は無視されて 255 が常に使用される)(デフォルト) ) // αチャンネル付き画像に対して描画を行う場合のみ意味がある関数 int SetUseNoBlendModeParam( int Flag );  まず、普通に SetDrawValidGraphCreateFlag( TRUE ); をした状態で MakeGraph 関数で 画像を作成すると、αチャンネルの無い画像となってしまいますので、 SetDrawValidGraphCreateFlag( TRUE ); をして、且つ SetDrawValidAlphaChannelGraphCreateFlag( TRUE ); もした上で MakeGraph 関数で 画像を作成すると、αチャンネル付きの描画対象に出来る画像が作成されます。  作成した描画対象に出来るαチャンネル付き画像を描画対象にして ClearDrawScreen を実行すると、RGBA の値全てが0に初期化されます。 で、書き込まれるアルファ値についてですが、 SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 255 ); SetDrawBright( 255,255,255 ); の状態で画像を描画すると元の画像そのままのものが描画されますが、αチャンネル にも見た目そのままの値が書き込まれます。(つまり透明情報がそのまま描画されます) SetDrawBlendMode( DX_BLENDMODE_ALPHA, 128 ); の状態で画像を描画すると書き込まれるRGB値と同じ様に書き込まれるα値も、 画像のα値の半分の値が書き込まれます。 (DX_BLENDMODE_ALPHA,128 で描画すると丁度50%不透明の描画なので) で、この半透明描画、理屈は合っていますが、直感的ではない結果になります。 例えばαチャンネル付き画像に SetDrawBlendMode( DX_BLENDMODE_ALPHA, 128 ); DrawBox( 0,0,100,100,GetColor(255,255,255), TRUE ); とした上で、このボックスを描画したαチャンネル付き画像を SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 255 ); DrawGraph( 0, 0, 描画対象に出来るαチャンネル付き画像, TRUE ); とした場合は、一見透明度50%の白い四角が描画されそうですが、 実際は灰色の透明度25%の四角が描画されます。  これは、αチャンネル付き画像に描画する際に以下の様な演算が行われて いるからです。 αチャンネル付き画像に書き込まれるR = (書き込み先のR×(255−書き込み元のA) + 書き込み元のR×書き込み元のA)÷255 αチャンネル付き画像に書き込まれるG = (書き込み先のG×(255−書き込み元のA) + 書き込み元のG×書き込み元のA)÷255 αチャンネル付き画像に書き込まれるB = (書き込み先のB×(255−書き込み元のA) + 書き込み元のB×書き込み元のA)÷255 αチャンネル付き画像に書き込まれるA = (書き込み先のA×(255−書き込み元のA) + 書き込み元のA×書き込み元のA)÷255 この演算を上記の例に当てはめると結果は以下の様になります。 (書き込み先は真っ黒(RGBA=0000)と仮定します) αチャンネル付き画像に書き込まれるR 128 = ( 0 x (255 - 128 ) + 255 x 128 ) / 255 αチャンネル付き画像に書き込まれるG 128 = ( 0 x (255 - 128 ) + 255 x 128 ) / 255 αチャンネル付き画像に書き込まれるB 128 = ( 0 x (255 - 128 ) + 255 x 128 ) / 255 αチャンネル付き画像に書き込まれるA 64 = ( 0 x (255 - 128 ) + 128 x 128 ) / 255 つまり、αチャンネル付き画像には灰色(R:128 G:128 B:128)の、透明度25%(64)の ピクセルが書き込まれてしまうわけです。 なので、透明度50%の白の四角をαチャンネル付き画像に書き込みたい場合は 以下の様にする必要があります。 SetUseNoBlendModeParam( TRUE ); SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 128 ); DrawBox( 0,0,100,100, GetColor(255,255,255), TRUE ); ブレンドモードを DX_BLENDMODE_NOBLEND にすると、書き込み時に使用される α値が必ず 255 になってしまうので、SetUseNoBlendModeParam( TRUE ); を実行して DX_BLENDMODE_NOBLEND 時の第二引数を書き込み時のα値に なるようにしています。  というわけで、ブレンドなしの場合は指定したα値がなんの演算もされずに そのままαチャンネル付き画像に R=255 G=255 B=255 A=128 の値が書き込まれる ので、その画像を後に DrawGraph( 0, 0, 描画対象に出来るαチャンネル付き画像, TRUE );  としても、予想通り透明度50%の四角が画面に描画されるわけです。 というわけで、描画可能なαチャンネル付き画像に対するブレンド描画は全然直感的ではありません。 別の例として、αチャンネル付き画像に SetDrawBlendMode( DX_BLENDMODE_ALPHA, 128 ); DrawBox( 0,0,100,100, GetColor(255,255,255), TRUE ); DrawBox( 0,0,100,100, GetColor(255,255,255), TRUE ); と、透明度50%の四角を2回描画したら、直感的には 透明度25%の真っ白(明度100%)の四角が残りそうですが、実際は 透明度62.5%の灰色の四角(明度75%)が残るだけとなります。  何故ならこの2回の描画を上記の式に当てはめると 1回目の DrawBox R: 128 = ( 0 x ( 255 - 128 ) + 255 x 128 ) 255 G: 128 = ( 0 x ( 255 - 128 ) + 255 x 128 ) 255 B: 128 = ( 0 x ( 255 - 128 ) + 255 x 128 ) 255 A: 64 = ( 0 x ( 255 - 128 ) + 128 x 128 ) 255 2回目の DrawBox R: 192 = ( 128 x ( 255 - 128 ) + 255 x 128 ) / 255 G: 192 = ( 128 x ( 255 - 128 ) + 255 x 128 ) / 255 B: 192 = ( 128 x ( 255 - 128 ) + 255 x 128 ) / 255 A: 96 = ( 64 x ( 255 - 128 ) + 128 x 128 ) / 255  となるからです。  そして、実際は直感的な描画結果を得るには以下の様な演算をする必要があります。 書き込まれるA = 書き込み先A+(255−書き込み先A)×書き込むA÷255 書き込まれるR = (書き込み先R×(書き込まれるA−書き込むA)+書き込むR×書き込むA)÷書き込まれるA 書き込まれるG = (書き込み先G×(書き込まれるA−書き込むA)+書き込むG×書き込むA)÷書き込まれるA 書き込まれるB = (書き込み先B×(書き込まれるA−書き込むA)+書き込むB×書き込むA)÷書き込まれるA  ただ、このような演算は簡単には出来ず、ちょっと考えただけでもかなりの グラフィックチップ性能が必要になりそうです。  というわけで、現時点では直感的ではない描画しか出来ません。 特殊な映像効果としては面白いことが出来るかもしれませんが、リアルな(理屈に合った) 映像表現をしようと思った場合はかなり扱い辛いかもしれません。  そんな感じですが、宜しければお使いになってみて下さい。m(_ _)m
Re: 画像バッファの扱いに関して ( No.4 )
名前:crow 日時:2007/03/23 01:34

遅くなりましたが、実装していただきありがとうございます。 どのような表現ができるか考えながら試していこうと思います。 ひとつ気になったのですが、 RGBは変化させず透明度のみを加算・減算するというのはできないでしょうか? たとえば、 αチャンネル付き画像に書き込まれるA = 書き込み先A + 書き込むA αチャンネル付き画像に書き込まれるR = 変化無し αチャンネル付き画像に書き込まれるG = 変化無し αチャンネル付き画像に書き込まれるB = 変化無し のようにです。 もしかしたらかなりムチャなことを言っているかもしれませんので、 実装が難しそうorハードウェア的に敷居が高そうだったらキッパリ諦めます(笑)
Re: 画像バッファの扱いに関して ( No.5 )
名前:管理人 日時:2007/03/23 16:42

 crowさんどうも、DXライブラリの管理人です。 > RGBは変化させず透明度のみを加算・減算するというのはできないでしょうか?  やっぱりそう思いますよね。(^^;  マイクロソフトの人もそう思ったのか、それともユーザーからの要望があったのかは わかりませんが、DirectX9 にはαチャンネルだけ独立した演算処理が出来るように なっています。  ただ、この機能は DirectX8 には無かった為、対応しているグラフィックチップは 大体2003〜2005年以降に登場した DirectX9 に対応したチップのみとなっています。 (NVIDIA では GeForce 6xxx シリーズ以降 ATI では RADEON 9600 以降)  ・・・・  これをハードウエア的に敷居が高いと判断するかどうかは人に因ると思いますが、 実装に関しましては、DXライブラリにこの機能を追加するとなると、DirectX9 用に DXライブラリのプログラムをすべて組み直さなければならないので、ちょっと対応は 難しいです。(DirectX9 用のコードに組み直す時間的コスト(組み上げ・デバッグに掛かる時間)と、 組み直したことにより得られる対価を比べると、ちょっと時間的コストの割合が大きすぎるので・・・)  申し訳ありません。m(_ _;m
Re: 画像バッファの扱いに関して ( No.6 )
名前:crow 日時:2007/03/23 17:41

なるほど、やっと最近出てきた機能なんですね。 私自身、いいグラフィックボードを使っているわけではないので、 その機能は使えませんね(笑) 教えていただき、ありがとうございました。 よくよく考えてみたところ、 白い描画可能な画像に透明度付きの画像を描画し、 それを「DX_BLENDMODE_MUL」で画面に合成すれば 似たようなことができそうな気がするので、 それでまずやってみようと思います。 もちろん、せっかく作っていただいたαチャンネルの機能もいろいろ試してみます。

Page: 1 |