お世話になります。
同じ画像ファイルをテクスチャとして共有している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;
}
以上、よろしくお願いします。