トップページ > 記事閲覧
複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい
名前:MOLE 日時: 2022/05/21 00:38

お世話になります。 同じ画像ファイルをテクスチャとして共有している3Dモデルを複数読み込むと、 同じ画像がVRAM上に複数読み込まれる(グラフィックハンドルが違う)仕様になっているようなのですが、 それをVRAM上の画像データも共有するようにする最適な方法はないでしょうか? 現在はテクスチャ画像を別のフォルダに置き意図的にリンク切れ状態にしてMV1LoadModelで読み込み MV1GetTextureColorFilePathでテクスチャファイル名を取得し まだ読み込んでいない画像ならMV1LoadTextureで読み込んでハンドルをMV1SetTextureGraphHandleで指定、 すでに読み込んである画像ならそのハンドルをMV1SetTextureGraphHandleで指定するという方法を使用しています。 一応下記のようなコードで動いてはいるのですが他にもっと良い方法がありますでしょうか? テクスチャを移動してリンク切れにしなくてもテクスチャを読み込まないように設定できたり、 モデルの読み込み時に直接グラフィックハンドルを指定するコールバック関数を指定できたりしないでしょうか? もしかして、そもそも同じ画像のテクスチャはグラフィックハンドルが違うだけで内部ではデータは共有されていたりするのでしょうか? 現在のコード(エラー処理省略) #include <vector> #include <stdio.h> #include "DxLib.h" struct TexData { char TextureName[260] = { 0 }; int GrHandle; int Count = 0; }; std::vector<TexData> TexList; int MV1LoadModel_TS(char *FileName) { int MHandle = MV1LoadModel(FileName); for (int i = 0; i < MV1GetTextureNum(MHandle); i++){ bool TexNonFlag = true; const char* TextureName = MV1GetTextureColorFilePath(MHandle, i); for (int j = 0; j < TexList.size(); j++){ if (strcmp(TextureName, TexList[j].TextureName) == 0) { MV1SetTextureGraphHandle(MHandle,i,TexList[j].GrHandle,true); TexList[j].Count++; TexNonFlag = false; break; } } if (TexNonFlag) { char FilePath[260]; sprintf_s(FilePath, 260, "data\\Tex\\%s", TextureName); TexData td; strcpy_s(td.TextureName, TextureName); td.GrHandle = MV1LoadTexture(FilePath); td.Count = 1; MV1SetTextureGraphHandle(MHandle, i, td.GrHandle, true); TexList.push_back(td); } } return MHandle; } int MV1DeleteModel_TS(int MHandle) { for (int i = 0; i < MV1GetTextureNum(MHandle); i++) { for (int j = 0; j < TexList.size(); j++) { const char* TextureName = MV1GetTextureColorFilePath(MHandle, i); if (strcmp(TextureName, TexList[j].TextureName) == 0) { MV1SetTextureGraphHandle(MHandle, i, -1, true); TexList[j].Count--; if (TexList[j].Count == 0) { DeleteGraph(TexList[j].GrHandle); TexList.erase(TexList.begin() + j); } break; } } } return MV1DeleteModel(MHandle); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { ChangeWindowMode(TRUE); SetGraphMode(1280, 720, 32); if (DxLib_Init() == -1)return -1; SetDrawScreen(DX_SCREEN_BACK); int MHandle[5]; SetCameraPositionAndTarget_UpVecY(VGet(0, 500, -600), VGet(0, 0, 0)); MHandle[0] = MV1LoadModel_TS("data\\Model_A.mv1"); MHandle[1] = MV1LoadModel_TS("data\\Model_B.mv1"); MHandle[2] = MV1LoadModel_TS("data\\Model_C.mv1"); MHandle[3] = MV1LoadModel_TS("data\\Model_D.mv1"); MHandle[4] = MV1LoadModel_TS("data\\Model_E.mv1"); for (int i = 0; i < 5; i++) { MV1SetPosition(MHandle[i], VGet(300 * i - 600, 0, 0)); } printfDx("テクスチャ数は%d\n", TexList.size()); for (int i = 0; i < TexList.size(); i++) { printfDx("テクスチャ画像「%s」は%d個のマテリアルで使われている\n", TexList[i].TextureName, TexList[i].Count); } while (!ProcessMessage()) { ClearDrawScreen(); for (int i = 0; i < 5; i++) { MV1DrawModel(MHandle[i]); } ScreenFlip(); } for (int i = 0; i < 5; i++) { MV1DeleteModel_TS(MHandle[i]); } DxLib_End(); return 0; } 以上、よろしくお願いします。
メンテ

Page: 1 |

Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.1 )
名前:管理人 日時:2022/05/21 21:54

> 一応下記のようなコードで動いてはいるのですが他にもっと良い方法がありますでしょうか? 現状の機能ではMOLEさんが組まれたコードの形が最適な実現方法だと思います > テクスチャを移動してリンク切れにしなくてもテクスチャを読み込まないように設定できたり、 > モデルの読み込み時に直接グラフィックハンドルを指定するコールバック関数を指定できたりしないでしょうか? 現状ではテクスチャを移動してリンク切れにしなくてもテクスチャを読み込まないように設定する機能や モデルの読み込み時に直接グラフィックハンドルを指定するコールバック関数を指定したりする機能はありません テクスチャを移動してリンク切れにしなくてもテクスチャを読み込まないように設定する関数や モデルの読み込み時に直接グラフィックハンドルを指定するコールバック関数を指定する関数の実装は可能ですが、 どちらを希望されますでしょうか? ( 機能的には前者の方が簡単なので、すぐ実装できると思います ) コールバック関数の場合は以下のような関数を追加することになると思います int MV1SetLoadTextureCallbackFunction( int ( *LoadTexCallback )( const char *FilePath, int *IsSelfDelete, void *Data ), void *Data ) ; コールバック関数の引数 FilePath で指定されるファイルのグラフィックハンドルを戻り値で返す形です あと、DXライブラリ側で DeleteGraph を使用してグラフィックハンドルを削除するのか、 自前で DeleteGraph を使用してグラフィックハンドルを削除するのかを指定するための引数 IsSelfDelete もあります // DXライブラリ側で DeleteGraph を実行する場合 *IsSelfDelete = FALSE ; // 自前で DeleteGraph を実行する場合 *IsSelfDelete = TRUE ; > もしかして、そもそも同じ画像のテクスチャはグラフィックハンドルが違うだけで内部ではデータは共有されていたりするのでしょうか? いえ、内部でもデータは共有されていません
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.2 )
名前:MOLE 日時:2022/05/21 23:46

>テクスチャを移動してリンク切れにしなくてもテクスチャを読み込まないように設定する関数や >モデルの読み込み時に直接グラフィックハンドルを指定するコールバック関数を指定する関数の実装は可能ですが、 新しく関数を追加していただけるとのことありがとうございます。 >どちらを希望されますでしょうか? >( 機能的には前者の方が簡単なので、すぐ実装できると思います ) どちらでも構いませんので、前者の方が機能的に簡単なのであれば「テクスチャを読み込まないように設定する関数」で大丈夫です。 (自分のコードだとファイルが無いと決まっているのに、存在を確認する為におそらく内部処理でHDDやSSDにアクセスしているのが処理時間のロスになっている気がしただけですので…) お手数をおかけしますが、よろしくお願いします。
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.3 )
名前:管理人 日時:2022/05/22 21:11

> どちらでも構いませんので、前者の方が機能的に簡単なのであれば「テクスチャを読み込まないように設定する関数」で大丈夫です。 了解です 早速機能を追加した暫定最新バージョンをアップしましたので、 よろしければこちらをダウンロードしてください m(_ _)m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.3 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい) 以下の関数を追加しました // 読み込む3Dモデルが使用するテクスチャファイルを読み込むかどうかを設定する // Flag TRUE:読み込む(デフォルト) FALSE:読み込まない int MV1SetLoadModelTextureLoad( int Flag ) ; 機能としては注釈の通り、3Dモデルが使用するテクスチャを読み込むかどうかの設定を するための関数です MV1LoadModel を実行する前に MV1SetLoadModelTextureLoad( FALSE ) ; を実行しておくことで、リンク切れにしなくてもテクスチャを読み込まないようにすることができます よろしければお試しください m(_ _)m
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.4 )
名前:MOLE 日時:2022/05/23 00:15

迅速に対応して頂き、ありがとうございます。 無事、暫定最新バージョンでテクスチャを読み込まず3Dモデルだけ読み込めるようになりました。 一つ気になった事があるのですが、 MV1SetLoadModelTextureLoad( FALSE )を設定して3Dモデルを読み込んでも8*8ドットの白いテクスチャが作成されているのですが、 これはモデルを読み込んだ直後にDeleteGraphで消してしまっても問題ないのでしょうか?
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.5 )
名前:管理人 日時:2022/05/24 02:26

> 一つ気になった事があるのですが、 > MV1SetLoadModelTextureLoad( FALSE )を設定して3Dモデルを読み込んでも8*8ドットの白いテクスチャが作成されているのですが、 > これはモデルを読み込んだ直後にDeleteGraphで消してしまっても問題ないのでしょうか? 恐らく問題ないと思いますが、DXライブラリ側でそもそも8*8ドットの白いテクスチャを作成しないようにしてみました ( 昨日のバージョンは、なるべく変更を少なくするために『テクスチャのファイルを読み込もうとするけどファイルが存在しなかった』を シミュレートするだけだったので、『テクスチャが読み込めなかったら8*8の白いテクスチャで代用する』の処理が走っていました ) 何度も申し訳ありませんが、よろしければお試しください m(_ _)m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.3 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい)
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.6 )
名前:MOLE 日時:2022/05/24 22:52

追加の修正ありがとうございます。 ただ他の不具合が発生してしまいまして、MV1GetTextureColorFilePath関数でテクスチャのパスが取得できなくなっている(NULLポインタが返る)ようです。 (テクスチャファイルだけでなくファイル名の読み込みもスキップされている?) これだと自前で画像を読み込む際にテクスチャのファイル名が取得できないたため、 読み込まなかったテクスチャのファイルパスをMV1GetTextureColorFilePath関数で取得できるようにして頂けると幸いです。 度々お手数をおかけして申し訳ありませんが、よろしくお願いします。
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.7 )
名前:管理人 日時:2022/05/27 01:35

あれ? おかしいですね… 手元で以下のようなプログラム( 読み込んだモデルのテクスチャ0番のファイル名を表示するプログラム )を 実行してみたところ、問題なくテクスチャ名( KabeTex.bmp )が表示されました #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int ModelHandle ; // ウインドウモードで起動 ChangeWindowMode( TRUE ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1 ; // テクスチャを読み込まない MV1SetLoadModelTextureLoad( FALSE ) ; // モデルの読み込み ModelHandle = MV1LoadModel( "ColTestStage.mqo" ) ; // ファイルパスの描画 DrawString( 0, 0, MV1GetTextureColorFilePath( ModelHandle, 0 ), GetColor( 255,255,255 ) ) ; // キー入力待ち WaitKey() ; // DXライブラリの後始末 DxLib_End() ; // ソフトの終了 return 0 ; } MOLEさんの環境では上記のプログラムでも0番目のテクスチャのファイル名が表示されませんでしょうか?
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.8 )
名前:MOLE 日時:2022/05/27 22:01

やはり自分の環境ではMV1SetLoadModelTextureLoadにFALSEをセットするとMV1GetTextureColorFilePathでNULLが帰ってくるようです。 (サンプルを実行するとDrawString第三引数にNULLを渡す事になるのでエラーで落ちます。) 試しにメタセコイアのデータを読み込んだら正常に取得できましたが、それをDxLibModelViewerでmv1に変換したらNULLが帰ってきました。 xファイルに変換したものも正常に動いたので、どうやらmv1形式だけNULLになるようです。 因みに私はBlender3.10でモデリングしてFBXにエクスポートし、DxLibModelViewerでmv1に変換したデータを使用しています。 最新のDxLibModelViewerでMV1に変換しているのですがモデルデータに何か問題があるのでしょうか? (症状が出るモデルファイルをギガファイル便にアップしました。→ttps://xgf.nu/4WXL) とりあえずmv1以外のファイルを使用すれば問題は回避出来ることはわかりましたが、 DxLibModelViewerはxファイルに法線マップを書き出せないのでmv1を使用できると有難いのですが… よろしくお願いします。
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.9 )
名前:管理人 日時:2022/05/28 02:29

詳しい状況のご説明と、ファイルのご提供ありがとうございます すみません、MV1ファイルの読み込み処理とそれ以外の3Dモデルファイルの読み込み処理が 分かれていて、MV1ファイルのみ MV1GetTextureColorFilePath の戻り値が NULL になるように なってしまっていました MV1ファイルの場合も正常にファイル名が取得できるように修正しましたので、お手数で申し訳ありませんが よろしければこちらをお試しください m(_ _;m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.3 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい)
メンテ
Re: 複数の3Dモデルで同じテクスチャ画像を共有している場合にVRAM上のデータでも共有したい ( No.10 )
名前:MOLE(解決) 日時:2022/05/28 21:44

無事MV1ファイルでもテクスチャのパスが取得できるようになりました。 これでテクスチャの共有が手軽にできるようになりました。 ありがとうございます。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存