トップページ > 過去ログ > 記事閲覧
ライト使用時の影について
名前:PATOLE 日時: 2013/05/09 22:42

お世話になっております。 DXライブラリをいつも使わせていただいております、PATOLEと申します。 立方体の3Dモデル(mqo形式)を、128*128個、大量に描画したのですが ディレクショナルライトなどを利用してライトを設定すると 影部分(暗くなっている部分)が僅かにみえてしまい、ちらついているようにみえてしまいます。 文章では分かりづらいので画像を用意してみました。 ttp://patolesoft.net/other/1.jpg 上記画像は、立方体のモデルを平面上に描画し、ディレクショナルライトをあてたものです。 ttp://patolesoft.net/other/2.jpg 上記画像は、SetUseLighting( FALSE );と設定し ライティング計算処理を無効にした際の画像です。 ライティング計算処理を無効にした場合は綺麗に描画されますが やはり、立体感がなくなってしまいます。 ライトを使用して、または使用しなくとも物体に明るい部分、暗い部分を作り、綺麗に描画する方法はないでしょうか。 1つの立方体に複数のマテリアルを使用するという方法もあるのですが 大量に描画することを優先したいので、できるだけマテリアルは1つに収めたいのです……。 何か良い方法がありましたら教えていただけると幸いです。 もう一つ、気になることがあるのですが 上記と全く同じプログラムで、モデルの『拡散光』だけを『0.80』から『0.10』や『1.00』などに設定すると 処理速度がかなり低下してしまうのはなぜでしょうか。

Page: 1 |

Re: ライト使用時の影について ( No.1 )
名前:管理人 日時:2013/05/12 03:38

立方体を大量に描画するとなると mqoファイルと MV1LoadModel などの3Dモデル関数を使用するより 以下の関数 CreateVertexBuffer DeleteVertexBuffer SetVertexBufferData CreateIndexBuffer DeleteIndexBuffer SetIndexBufferData DrawPolygonIndexed3D_UseVertexBuffer を使用して立方体の配置情報から自前でポリゴン座標を計算して描画するほうが圧倒的に高速に描画できると思います ( 一回の DrawPolygonIndexed3D_UseVertexBuffer で複数の立方体を一度に描画するので、 一個一個 MV1DrawModel するより速くなります ) また、どうしても計算誤差の関係で立方体の隙間にある影部分は消せないと思いますので、 自前でポリゴン座標を算出する際は ・見えないポリゴンは省く ようにすることで、描画するポリゴンも減らすことができ、且つ隣接する立方体の隙間部分にある 影も消すことができます 処理の流れは  >> 初期化パート   1.立方体の配置情報を読み込む( 立方体に貼るテクスチャも読み込む )   2.立方体群の見える面を洗い出す( 見えない面は省く )   3.見える面( ポリゴン )を描画するのに必要な頂点数の頂点バッファ、インデックス数のインデックスバッファを     CreateVertexBuffer, CreateIndexBuffer を使用して作成する   4.頂点データ、インデックスデータを SetVertexBufferData, SetIndexBufferData でセットする     ( 頂点座標はワールド座標 )  >> ループパート    5.ループでは用意した頂点データ、インデックスデータを使用して DrawPolygonIndexed3D_UseVertexBuffer で描画する というような感じです DrawPolygonIndexed3D_UseVertexBuffer を使用して画面に2個ポリゴンを描画するサンプルプログラムが ありましたので、よろしければご覧ください #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { VERTEX3D Vertex[ 4 ] ; WORD Index[ 6 ] ; int VertexBufHandle ; int IndexBufHandle ; // DXライブラリの初期化 ChangeWindowMode( TRUE ) ; if( DxLib_Init() < 0 ) { // エラーが発生したら直ちに終了 return -1 ; } // 4頂点分の頂点バッファを作成 VertexBufHandle = CreateVertexBuffer( 4, DX_VERTEX_TYPE_NORMAL_3D ) ; // 6個分のインデックスバッファを作成 IndexBufHandle = CreateIndexBuffer( 6, DX_INDEX_TYPE_16BIT ) ; // 4頂点分のデータをセット Vertex[ 0 ].pos = VGet( 100.0f, 100.0f, 0.0f ) ; Vertex[ 0 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ; Vertex[ 0 ].dif = GetColorU8( 255,255,255,255 ) ; Vertex[ 0 ].spc = GetColorU8( 0, 0, 0, 0 ) ; Vertex[ 0 ].u = 0.0f ; Vertex[ 0 ].v = 0.0f ; Vertex[ 0 ].su = 0.0f ; Vertex[ 0 ].sv = 0.0f ; Vertex[ 1 ].pos = VGet( 250.0f, 100.0f, 0.0f ) ; Vertex[ 1 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ; Vertex[ 1 ].dif = GetColorU8( 255, 0,255,255 ) ; Vertex[ 1 ].spc = GetColorU8( 0, 0, 0, 0 ) ; Vertex[ 1 ].u = 0.0f ; Vertex[ 1 ].v = 0.0f ; Vertex[ 1 ].su = 0.0f ; Vertex[ 1 ].sv = 0.0f ; Vertex[ 2 ].pos = VGet( 100.0f, 300.0f, 0.0f ) ; Vertex[ 2 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ; Vertex[ 2 ].dif = GetColorU8( 0,255,255,255 ) ; Vertex[ 2 ].spc = GetColorU8( 0, 0, 0, 0 ) ; Vertex[ 2 ].u = 0.0f ; Vertex[ 2 ].v = 0.0f ; Vertex[ 2 ].su = 0.0f ; Vertex[ 2 ].sv = 0.0f ; Vertex[ 3 ].pos = VGet( 400.0f, 200.0f, 0.0f ) ; Vertex[ 3 ].norm = VGet( 0.0f, 0.0f, -1.0f ) ; Vertex[ 3 ].dif = GetColorU8( 0,255,255,255 ) ; Vertex[ 3 ].spc = GetColorU8( 0, 0, 0, 0 ) ; Vertex[ 3 ].u = 0.0f ; Vertex[ 3 ].v = 0.0f ; Vertex[ 3 ].su = 0.0f ; Vertex[ 3 ].sv = 0.0f ; // 2ポリゴン分のインデックスデータをセット Index[ 0 ] = 0 ; Index[ 1 ] = 1 ; Index[ 2 ] = 2 ; Index[ 3 ] = 3 ; Index[ 4 ] = 2 ; Index[ 5 ] = 1 ; // 頂点データを頂点バッファに転送 SetVertexBufferData( 0, Vertex, 4, VertexBufHandle ) ; // インデックスデータをインデックスバッファに転送 SetIndexBufferData( 0, Index, 6, IndexBufHandle ) ; // 頂点バッファとインデックスバッファを使用した2ポリゴンの描画 DrawPolygonIndexed3D_UseVertexBuffer( VertexBufHandle, IndexBufHandle, DX_NONE_GRAPH, FALSE ) ; // キー入力待ちをする WaitKey() ; // DXライブラリの後始末 DxLib_End() ; // ソフトの終了 return 0 ; } ただ、この方法には以下のような面倒な点があります ・一度の DrawPolygonIndexed3D_UseVertexBuffer で使用できるテクスチャは一つなので、  何種類もある立方体のテクスチャを一つのテクスチャに纏める必要がある ・一度に描画できるインデックスデータの数、頂点データの数の最大数は 65536個 なので  一度に描画できるポリゴンの数は最大 65536 / 3 = 21845個、  128 * 128 の立方体を全面描画するのに必要なポリゴン数は 12 * 128 * 128 = 196608個( 立方体一つ12ポリ )  なので、見えない部分を省いても 21845個を超える場合があるので複数の頂点バッファ、インデックスバッファを  使用する必要がある ・頂点バッファ、インデックスバッファを使用する立方体描画は立方体が動かないことを前提に最適化された  処理なので、仮に動く立方体が存在する場合は扱いを別にする必要がある ( 動く立方体だけ MV1DrawModel を使用するなど ) DrawPolygonIndexed3D_UseVertexBuffer などの扱いで不明な点がありましたらお訊ねください と、ここまでご説明したところでもう一つ方法を思いつきました 速度面では DrawPolygonIndexed3D_UseVertexBuffer を使用する場合より大幅に遅くなりますが、 3Dサンプルプログラムの迷路 http://homepage2.nifty.com/natupaji/DxLib/program/dxprogram_3Dmeiro.html と同じ方法で立方体の各面をそれぞれフレームに分けて、見えない面を非表示にして描画することで 件の問題の影部分の面がちらちら見える現象は防げると思います DrawPolygonIndexed3D_UseVertexBuffer を使用する場合よりかなり遅くなるので実用的な速度が得られるかは 分かりませんが、実装難度はかなり低くなると思います
Re: ライト使用時の影について ( No.2 )
名前:PATOLE 日時:2013/05/12 06:06

ご返答ありがとうございます。 なるほど、そのような方法があったのですね。 その上記のサンプルプログラムで、お尋ねしたいことがあります。 >一度の DrawPolygonIndexed3D_UseVertexBuffer で使用できるテクスチャは一つなので、  何種類もある立方体のテクスチャを一つのテクスチャに纏める必要がある とありますが、2種類の立方体(テクスチャ)を描画するとして DrawPolygonIndexed3D_UseVertexBufferを1度だけ呼び出して描画する方法はあるのでしょうか。 その、1つのテクスチャにまとめて描画するにはどうすれば良いのでしょうか。 もう一つの方法についてですが >3Dサンプルプログラムの迷路 と同じように描画するとして MV1DrawModelを一度呼び出すのと MV1DrawFrameを6回、または見える面だけを処理するとして3回呼び出すとすれば、どちらのほうが高速に処理することが可能なのでしょうか。 以上、2点について教えていただけると幸いです。
Re: ライト使用時の影について ( No.3 )
名前:PATOLE(解決) 日時:2013/05/12 14:57

連投失礼致します。 上記の、数種類のテクスチャを描画する方法については自己解決しました。 お騒がせして申し訳ありません。 構造体VERTEX3Dの、u,vを必要な画像の種類に応じてセットすればよかったのですね。 ブロックとブロックが離れている場合は、その分だけインデックスデータを作成して SetIndexBufferDataすれば良いのでしょうか。 実装は少し大変そうですが、このほうが高速に描画できるというのであれば実装してみる価値があると思います。 ありがとうございます。
Re: ライト使用時の影について ( No.4 )
名前:管理人 日時:2013/05/19 23:06

> MV1DrawModelを一度呼び出すのと > MV1DrawFrameを6回、または見える面だけを処理するとして3回呼び出すとすれば、どちらのほうが高速に処理することが可能なのでしょうか。 MV1DrawModel を一度だけ呼び出す方が高速です > ブロックとブロックが離れている場合は、その分だけインデックスデータを作成して > SetIndexBufferDataすれば良いのでしょうか。 はい、そうです あと、二つのブロックにはさまれた部分は見えることが無く描画する必要が無いので、 その部分のポリゴンを省くと高速化できます

Page: 1 |