chapter8のマテリアルを張ることが出来ません
色は付くのですが参考書の通りではなく
ひかりの角度によって色が変わっているようです?
最後にコードを書いておくのですが
1131行目のcmdList->SetDescriptorHeaps(1, &materialDescHeap);
の一文をコメントアウトしないとモデルすら出ない状況です
なので問題はmaterialDescHeapを設定している部分かと思い
参考書記載のコードや、配布されているサンプルコードと見比べたのですが
何処が間違っているのか分かりませんでした。
環境は
Windows10
visualstudio2019
DirectXTexライブラリを使用しています
理解が足りず、具体的な質問にならないのが申し訳ありませんが
なにか、この問題に心当たりがある方はお助け下さい。
#include <Windows.h>
#include<tchar.h>
#include<d3d12.h>
#include<dxgi1_6.h>
#include<DirectXMath.h>
#include<vector>
#include<d3dcompiler.h>
#include <DirectXTex.h>
#ifdef _DEBUG
#include<iostream>
#endif
using namespace std;
using namespace DirectX;
// x84用のデータがないのか、x64でないとDirectXTexが動かない
#pragma comment(lib,"DirectXTex.lib")
#pragma comment(lib,"d3d12.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"d3dcompiler.lib")
///@brief コンソール画面にフォーマット付き文字列を表示
///@param format フォーマット(%dとか%fとかの)
///@param 可変長引数
///@remarks この関数はデバッグ用です。デバッグ時にしか動作しません
void DebugOutputFormatString(const char* format, ...)
{
#ifdef _DEBUG
va_list valist;
va_start(valist, format);
vprintf(format, valist);
va_end(valist);
#endif
}
// 面倒だけど書かなければいけない関数
LRESULT WindowProcedure(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
// ウィンドウが破棄されたら呼ばれます
if (msg == WM_DESTROY)
{
PostQuitMessage(0); // OSに対して「もうこのアプリは終わるんや」と伝える
return 0;
}
return DefWindowProc(hwnd, msg, wparam, lparam); // 規定の処理を行う
}
const unsigned int window_width = 1280;
const unsigned int window_height = 720;
ID3D12Device* device = nullptr;
IDXGIFactory6* dxgiFactory = nullptr;
IDXGISwapChain4* swapchain = nullptr;
ID3D12CommandAllocator* cmdAllocator = nullptr;
ID3D12GraphicsCommandList* cmdList = nullptr;
ID3D12CommandQueue* cmdQueue = nullptr;
// デバックレイヤーを有効化する
void EnableDebugLayer()
{
ID3D12Debug* debugLayer = nullptr;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugLayer))))
{
debugLayer->EnableDebugLayer(); // デバックレイヤーを有効化する
debugLayer->Release(); // 有効化したらインターフェースを解放する
}
}
#ifdef _DEBUG
int main()
{
#else
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
#endif
DebugOutputFormatString("Show window test.");
// getchar();
// ウィンドウクラスの生成&登録
WNDCLASSEX w = {};
w.cbSize = sizeof(WNDCLASSEX);
w.lpfnWndProc = (WNDPROC)WindowProcedure; // コールバック関数の指定
w.lpszClassName = _T("DX12Sample"); // アプリケーションクラス名(適当でいいです)
w.hInstance = GetModuleHandle(0); // ハンドルの取得
RegisterClassEx(&w); // アプリケーションクラス(こういうの作るからよろしくってOSに予告する)
RECT wrc = { 0,0, window_width, window_height }; // ウィンドウサイズを決める
// 関数を使ってウィンドウのサイズを補正する
AdjustWindowRect(&wrc, WS_OVERLAPPEDWINDOW, false); // ウィンドウのサイズはちょっと面倒なので関数を使って補正する
//ウィンドウオブジェクトの生成
HWND hwnd = CreateWindow
(
w.lpszClassName, // クラス名指定
_T("DX12テスト"), // タイトルバーの文字
WS_OVERLAPPEDWINDOW, // タイトルバーと境界線があるウィンドウです
CW_USEDEFAULT, // 表示X座標はOSにお任せします
CW_USEDEFAULT, // 表示Y座標はOSにお任せします
wrc.right - wrc.left, // ウィンドウ幅
wrc.bottom - wrc.top, // ウィンドウ高
nullptr, // 親ウィンドウハンドル
nullptr, // メニューハンドル
w.hInstance, // 呼び出しアプリケーションハンドル
nullptr // 追加パラメータ
);
#ifdef _DEBUG
//デバッグレイヤーをオンに
//デバイス生成時前にやっておかないと、デバイス生成後にやると
//デバイスがロスとしてしまうので注意
EnableDebugLayer();
#endif
//DirectX12まわり初期化
//フィーチャレベル列挙
D3D_FEATURE_LEVEL levels[] =
{
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
};
// DXGIのエラーメッセージを取得できるようにする
#ifdef _DEBUG
CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(&dxgiFactory));
#else
CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory));
#endif // _DEBUG
auto result = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory));
// アダプター列挙用
std::vector <IDXGIAdapter*> adapters;
// ここに特定の名前を持つアダプターオブジェクトが入る
IDXGIAdapter* tmpAdapter = nullptr;
for (int i = 0; dxgiFactory->EnumAdapters(i, &tmpAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
{
adapters.push_back(tmpAdapter);
}
for (auto adpt : adapters)
{
DXGI_ADAPTER_DESC adesc = {};
adpt->GetDesc(&adesc); // アダプターの説明オブジェクト取得
std::wstring strDesc = adesc.Description;
// 探したいアダプターの名前を確認
if (strDesc.find(L"NVIDIA") != std::string::npos)
{
tmpAdapter = adpt;
break;
}
}
// Direct3Dデバイスの初期化
D3D_FEATURE_LEVEL featureLevel;
for (auto l : levels)
{
if (D3D12CreateDevice(nullptr, l, IID_PPV_ARGS(&device)) == S_OK)
{
featureLevel = l;
break; // 生成可能なバージョンが見つかったらループを打ち切り
}
}
result = device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAllocator));
result = device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAllocator, nullptr, IID_PPV_ARGS(&cmdList));
// コマンドキュー
D3D12_COMMAND_QUEUE_DESC cmdQueueDesc = {};
cmdQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; // タイムアウトなし
cmdQueueDesc.NodeMask = 0; // アダプターを一つしか使わない場合は0
cmdQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; // プライオリティ特に指定なし
cmdQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; // ここはコマンドリストと合わせる
//コマンドキュー生成
result = device->CreateCommandQueue(&cmdQueueDesc, IID_PPV_ARGS(&cmdQueue));
// スワップチェイン
DXGI_SWAP_CHAIN_DESC1 swapchainDesc = {};
swapchainDesc.Width = window_width; // 画面解像度(幅)
swapchainDesc.Height = window_height; // 画面解像度(高)
swapchainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // ピクセルフォーマット
swapchainDesc.Stereo = false; // ステレオ表示フラグ
swapchainDesc.SampleDesc.Count = 1; // マルチサンプルの指定
swapchainDesc.SampleDesc.Quality = 0; // マルチサンプルの指定
swapchainDesc.BufferUsage = DXGI_USAGE_BACK_BUFFER; // これで流用可
swapchainDesc.BufferCount = 2; // ダブルバッファなら2でよい
swapchainDesc.Scaling = DXGI_SCALING_STRETCH; // これでバックバッファは伸び縮み可能
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // フリップ後は速やかに破棄
swapchainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // 特になし
swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // ウィンドウ⇔フルスクリーン
result = dxgiFactory->CreateSwapChainForHwnd
(
cmdQueue, // コマンドキューオブジェクト
hwnd, // ウィンドウハンドル
&swapchainDesc, // スワップチェーン設定
nullptr, // ひとまず無視
nullptr, // ひとまず無視
(IDXGISwapChain1**)&swapchain // スワップチェインオブジェクト取得用
);
// ディスクリプタヒープの作成(Direct12魔導書:P81)
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; // レンダーターゲットビューなのでRTV
heapDesc.NodeMask = 0; // 複数のGPUがある場合に識別を行う為のビットフラグ
heapDesc.NumDescriptors = 2; // 表裏の2つ
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; // 特に指定なし
ID3D12DescriptorHeap* rtvHeaps = nullptr;
result = device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&rtvHeaps));
// ここまでで「ビュー用のメモリを確保しただけ状態」
// スワップチェインとメモリを紐付ける
DXGI_SWAP_CHAIN_DESC swcDesc = {};
result = swapchain->GetDesc(&swcDesc);
std::vector<ID3D12Resource*> backBuffers(swcDesc.BufferCount);
D3D12_CPU_DESCRIPTOR_HANDLE handle = rtvHeaps->GetCPUDescriptorHandleForHeapStart();
// ガンマ補正に対応する
// SRGBレンダーターゲットビューの設定
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; // ガンマ補正あり(sRGB)
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
for (size_t i = 0; i < swcDesc.BufferCount; ++i)
{
result = swapchain->GetBuffer(static_cast<UINT>(i), IID_PPV_ARGS(&backBuffers[i]));
device->CreateRenderTargetView
(
backBuffers[i], // バッファ―
&rtvDesc, // 今回はnullptr
handle // ディスクリプタヒープハンドル
);
handle.ptr += device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
}
// 深度バッファの作成
// 深度バッファの仕様
D3D12_RESOURCE_DESC depthResDesc = {};
depthResDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; // 2次元のテクスチャデータ
depthResDesc.Width = window_width; // 幅と高さはレンダーターゲットと同じ
depthResDesc.Height = window_height; // 上に同じ
depthResDesc.DepthOrArraySize = 1; // テクスチャ配列でもないし3Dテクスチャでもない
depthResDesc.Format = DXGI_FORMAT_D32_FLOAT; // 深度値書き込み用フォーマット
depthResDesc.SampleDesc.Count = 1; // サンプルは1ピクセル当たり1つ
depthResDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; // 深度ステンシルとして使用
depthResDesc.MipLevels = 1;
depthResDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
depthResDesc.Alignment = 0;
// 深度値用ヒーププロパティ
D3D12_HEAP_PROPERTIES depthHeapProp = {};
depthHeapProp.Type = D3D12_HEAP_TYPE_DEFAULT; // DEFAULTだから後はUNKNOWNでよし
depthHeapProp.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
depthHeapProp.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
//このクリアバリューが重要な意味を持つ
D3D12_CLEAR_VALUE depthClearValue = {};
depthClearValue.DepthStencil.Depth = 1.0f; // 深さ1(最大値)でクリア
depthClearValue.Format = DXGI_FORMAT_D32_FLOAT; // 32bit深度値としてクリア
ID3D12Resource* depthBuffer = nullptr;
result = device->CreateCommittedResource
(
&depthHeapProp,
D3D12_HEAP_FLAG_NONE,
&depthResDesc,
D3D12_RESOURCE_STATE_DEPTH_WRITE, // デプス書き込みに使用
&depthClearValue,
IID_PPV_ARGS(&depthBuffer)
);
// 深度バッファビューの作成
// 深度のためのデスクリプタヒープ作成
D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; // 深度に使う、それだけわかってろ。らしい
dsvHeapDesc.NumDescriptors = 1; // 深度ビュー1つのみ
dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; // デプスステンシルビューとして使う
//dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
ID3D12DescriptorHeap* dsvHeap = nullptr;
result = device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&dsvHeap));
// 深度ビュー作成
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
dsvDesc.Format = DXGI_FORMAT_D32_FLOAT; // デプス値に32bit使用
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; // 2Dテクスチャ
dsvDesc.Flags = D3D12_DSV_FLAG_NONE; // フラグは特になし
device->CreateDepthStencilView
(
depthBuffer, // ID3D12Resourceオブジェクトへのポインタ。
&dsvDesc, // D3D12_DEPTH_STENCIL_VIEW_DESC構造体へのポインター。
dsvHeap->GetCPUDescriptorHandleForHeapStart()
);
ID3D12Fence* fence = nullptr;
UINT64 fenceVal = 0;
result = device->CreateFence(fenceVal, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
// ウィンドウ表示
ShowWindow(hwnd, SW_SHOW);
//XMFLOAT3 vertices[] =
//{
// //{ -1.0f, -1.0f, 0.0f }, // 左下
// //{ -1.0f, 1.0f, 0.0f }, // 左上
// //{ 1.0f, -1.0f, 0.0f } // 右下
// //{ -0.5f, -0.7f, 0.0f }, // 左下
// //{ -0.0f, 0.7f, 0.0f }, // 左上
// //{ 0.5f, -0.7f, 0.0f } // 右下
// { -0.4f, -0.7f, 0.0f }, // 左下 : インデックス0
// { -0.4f, 0.7f, 0.0f }, // 左上 : インデックス1
// { 0.4f, -0.7f, 0.0f }, // 右下 : インデックス2
// { 0.4f, 0.7f, 0.0f } // 右上 : インデックス3
//};
//struct Vertex
//{
// XMFLOAT3 pos; // XYZ座標
// XMFLOAT2 uv; // UV座標
//};
//Vertex vertices[] =
//{
// // 初期位置
// { {-0.5f,-0.9f, 0.0f} ,{ 0.0f, 1.0f} }, // 左下
// { {-0.5f, 0.9f, 0.0f} ,{ 0.0f, 0.0f} }, // 左上
// { { 0.5f,-0.9f, 0.0f} ,{ 1.0f, 1.0f} }, // 右下
// { { 0.5f, 0.9f, 0.0f} ,{ 1.0f, 0.0f} }, // 右上
// // 左上
// { { 0.0f, 100.0f, 0.0f} ,{ 0.0f, 1.0f} }, // 左下
// { { 0.0f, 0.0f, 0.0f} ,{ 0.0f, 0.0f} }, // 左上
// { { 100.0f, 100.0f, 0.0f} ,{ 1.0f, 1.0f} }, // 右下
// { { 100.0f, 0.0f, 0.0f} ,{ 1.0f, 0.0f} }, // 右上
// //3D化初期値
// { {-1.0f,-1.0f, 0.0f} ,{ 0.0f, 1.0f} }, // 左下
// { {-1.0f, 1.0f, 0.0f} ,{ 0.0f, 0.0f} }, // 左上
// { { 1.0f,-1.0f, 0.0f} ,{ 1.0f, 1.0f} }, // 右下
// { { 1.0f, 1.0f, 0.0f} ,{ 1.0f, 0.0f} }, // 右上
//};
// PMDヘッダ構造体
struct PMDHeader
{
float version; // 例:00 00 80 3F == 1.00
char model_name[20]; // モデル名
char comment[256]; // モデルコメント
};
FILE* fp;
PMDHeader pmdheader = {};
char signature[3]; // シグネチャ
auto err = fopen_s(&fp, "初音ミク.pmd", "rb");
fread(signature, sizeof(signature), 1, fp);
fread(&pmdheader, sizeof(pmdheader), 1, fp);
// PMD頂点構造体
struct PMDVertex
{
XMFLOAT3 pos; // 頂点座標 :12バイト
XMFLOAT3 normal; // 法線ベクトル:12バイト
XMFLOAT2 uv; // UV座標 :8バイト
unsigned short boneNo[2]; // ボーン番号 :4バイト
unsigned char boneWeight; // ボーン影響度:1バイト
unsigned char edgeFlg; // 輪郭線フラグ:1バイト
}; // 合計38バイト:パディングされて40バイトにされズレが生じる可能性がある(今回は大丈夫らしい)
// 頂点全て読み込む
unsigned int vertNum; // 総頂点数
fread(&vertNum, sizeof(vertNum), 1, fp);
#pragma pack(1) // ここから1バイトパッキング:アライメントは発生しない
//PMDマテリアル構造体
struct PMDMaterial
{
XMFLOAT3 diffuse; // ディフューズ色
float alpha; // ディフューズα
float specularity; // スペキュラの強さ(乗算値)
XMFLOAT3 specular; // スペキュラ色
XMFLOAT3 ambient; // アンビエント色
unsigned char toonIdx; // トゥーン番号(後述)
unsigned char edgeFlg; // マテリアル毎の輪郭線フラグ
//2バイトのパディングが発生!!
unsigned int indicesNum; // このマテリアルが割り当たるインデックス数
char texFilePath[20]; // テクスチャファイル名(プラスアルファ…後述)
};
// 70バイトのはず…でもパディングが発生するため72バイト
// #pragma packを使用することで、70バイトで定義
#pragma pack() // 1バイトパッキング解除
// シェーダ側に投げられるマテリアルデータ
struct MaterialForHlsl
{
XMFLOAT3 diffuse; // ディフューズ色
float alpha; // ディフューズα
XMFLOAT3 specular; // スペキュラ色
float specularity; // スペキュラの強さ(乗算値)
XMFLOAT3 ambient; // アンビエント色
};
// それ以外のマテリアルデータ
struct AdditionalMaterial
{
std::string texPath;// テクスチャファイルパス
int toonIdx; // トゥーン番号
bool edgeFlg; // マテリアル毎の輪郭線フラグ
};
//まとめたもの
struct Material
{
unsigned int indicesNum; // インデックス数
MaterialForHlsl material;
AdditionalMaterial additional;
};
constexpr unsigned int pmdvertex_size = 38; // 頂点1つあたりのサイズ
std::vector<unsigned char> vertices(vertNum * pmdvertex_size); // バッファ確保
fread(vertices.data(), vertices.size(), 1, fp); // 一気に読み込み
unsigned int indicesNum;//インデックス数
fread(&indicesNum, sizeof(indicesNum), 1, fp);
// リソース設定構造体
D3D12_HEAP_PROPERTIES heapprop = {};
heapprop.Type = D3D12_HEAP_TYPE_UPLOAD; // ヒープの種別(mapする必要があるならUPLOAD)
heapprop.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; // CPUのページング設定
heapprop.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; // メモリプールが何処かを示す
D3D12_RESOURCE_DESC resdesc = {};
resdesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; // バッファに使うのでBUFFERを指定
resdesc.Width = vertices.size(); // 幅で全部まかなうのでsizeof(全頂点)とする
resdesc.Height = 1; // 幅で表現しているので1
resdesc.DepthOrArraySize = 1; // 1でヨシ(らしい)
resdesc.MipLevels = 1; // 1でヨシ(らしい)
resdesc.Format = DXGI_FORMAT_UNKNOWN; // 画像ではないのでUNKNOWN
resdesc.SampleDesc.Count = 1; // SampleDesc.Count= 1;とする(?)
resdesc.Flags = D3D12_RESOURCE_FLAG_NONE; // NONEでヨシ
resdesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; // D3D12_TEXTURE_LAYOUT_ROW_MAJOR(P112を参照)
//UPLOAD(確保は可能)
ID3D12Resource* vertBuff = nullptr;
result = device->CreateCommittedResource
(
&heapprop, // ヒープ設定構造体のアドレス
D3D12_HEAP_FLAG_NONE, // 特に指定がない場合D3D12_HEAP_FLAG_NONEでよい(てか大概指定はない)
&resdesc, // リソース設定構造体のアドレス
D3D12_RESOURCE_STATE_GENERIC_READ, // GPU側からは読み取り専用なのでGENERIC_READ
nullptr, // 使わないのでnullptr
IID_PPV_ARGS(&vertBuff) // IID_PPV_ARGSにいまだ慣れない
);
// 頂点情報のコピー(マップ)
//XMFLOAT3* vertMap = nullptr;
unsigned char* vertMap = nullptr;
result = vertBuff->Map(0, nullptr, (void**)&vertMap);
std::copy(std::begin(vertices), std::end(vertices), vertMap); // 書き込み
vertBuff->Unmap(0, nullptr); // マップ解除命令
// 頂点バッファビューの作成
D3D12_VERTEX_BUFFER_VIEW vbView = {};
vbView.BufferLocation = vertBuff->GetGPUVirtualAddress(); // バッファの仮想アドレス
vbView.SizeInBytes = static_cast<UINT>(vertices.size()); // 全バイト数
vbView.StrideInBytes = pmdvertex_size; // 1頂点あたりのバイト数
std::vector<unsigned short> indices(indicesNum);
fread(indices.data(), indices.size() * sizeof(indices[0]), 1, fp);
// PMDモデルのマテリアルを読み込む
unsigned int materialNum; // マテリアル数
fread(&materialNum, sizeof(materialNum), 1, fp);
// 転送用のデータ作成
std::vector<Material> materials(materialNum);
std::vector<PMDMaterial> pmdMaterials(materialNum);
fread(pmdMaterials.data(), pmdMaterials.size() * sizeof(PMDMaterial), 1, fp); // 一気に読み込む
for (int i = 0; i < pmdMaterials.size(); ++i)
{
materials[i].indicesNum = pmdMaterials[i].indicesNum;
materials[i].material.diffuse = pmdMaterials[i].diffuse;
materials[i].material.alpha = pmdMaterials[i].alpha;
materials[i].material.specular = pmdMaterials[i].specular;
materials[i].material.specularity = pmdMaterials[i].specularity;
materials[i].material.ambient = pmdMaterials[i].ambient;
//materials[i].additional.toonIdx = pmdMaterials[i].toonIdx;
}
fclose(fp);
// インデックスの実装
// 頂点3っがセットの時計回り
//unsigned short indices[] = { 0,1,2, 2,1,3 };
ID3D12Resource* idxBuff = nullptr;
//設定は、バッファのサイズ以外頂点バッファの設定を使いまわしてOKのはず
resdesc.Width = indices.size() * sizeof(indices[0]);
result = device->CreateCommittedResource
(
&heapprop,
D3D12_HEAP_FLAG_NONE,
&resdesc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&idxBuff)
);
//作ったバッファにインデックスデータをコピー
unsigned short* mappedIdx = nullptr;
idxBuff->Map(0, nullptr, (void**)&mappedIdx);
std::copy(std::begin(indices), std::end(indices), mappedIdx);
idxBuff->Unmap(0, nullptr);
//インデックスバッファビューを作成
D3D12_INDEX_BUFFER_VIEW ibView = {};
ibView.BufferLocation = idxBuff->GetGPUVirtualAddress();
ibView.Format = DXGI_FORMAT_R16_UINT;
ibView.SizeInBytes = static_cast<UINT>(indices.size() * sizeof(indices[0]));
//マテリアルバッファを作成
auto materialBuffSize = sizeof(MaterialForHlsl);
materialBuffSize = (materialBuffSize + 0xff) & ~0xff;
ID3D12Resource* materialBuff = nullptr;
// ここのresdescとheappropを設定し直す必要がありそう?
resdesc.Width = materialBuffSize * materialNum;
result = device->CreateCommittedResource
(
&heapprop,
D3D12_HEAP_FLAG_NONE,
&resdesc, //勿体ないけど仕方ないですね
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&materialBuff)
);
// マップマテリアルにコピー
char* mapMaterial = nullptr;
result = materialBuff->Map(0, nullptr, (void**)&mapMaterial);
for (auto& m : materials)
{
// アライメントサイズに違いがあるので、かなり強制的なキャストをしている
*((MaterialForHlsl*)mapMaterial) = m.material; // データコピー
mapMaterial += materialBuffSize; // 次のアライメント位置まで進める
}
materialBuff->Unmap(0, nullptr);
// マテリアル用ディスクリプタヒープの作成
ID3D12DescriptorHeap* materialDescHeap = nullptr;
D3D12_DESCRIPTOR_HEAP_DESC materialDescHeapDesc = {};
materialDescHeapDesc.NumDescriptors = materialNum; // マテリアル数ぶん(定数1つ、テクスチャ3つ)
materialDescHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
materialDescHeapDesc.NodeMask = 0;
materialDescHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; // デスクリプタヒープ種別
result = device->CreateDescriptorHeap(&materialDescHeapDesc, IID_PPV_ARGS(&materialDescHeap));//生成
D3D12_CONSTANT_BUFFER_VIEW_DESC matCBVDesc = {};
matCBVDesc.BufferLocation = materialBuff->GetGPUVirtualAddress(); // バッファアドレス
matCBVDesc.SizeInBytes = static_cast<UINT>(materialBuffSize); // マテリアルの256アライメントサイズ
// 先頭を記録
auto matDescHeapH = materialDescHeap->GetCPUDescriptorHandleForHeapStart();
for (size_t i = 0; i < materialNum; i++)
{
device->CreateConstantBufferView(&matCBVDesc, matDescHeapH);
matDescHeapH.ptr += device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
matCBVDesc.BufferLocation += materialBuffSize;
}
ID3DBlob* vsBlob = nullptr;
ID3DBlob* psBlob = nullptr;
ID3DBlob* errorBlob = nullptr;
result = D3DCompileFromFile
(
L"BaiscVertexShader.hlsl", // シェーダー名
nullptr, // defineはなし
D3D_COMPILE_STANDARD_FILE_INCLUDE, // インクルードはデフォルト
"BasicVS", "vs_5_0", // 関数はBasicVS、対象シェーダーはvs_5_0
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, // デバック用および最適化なし
0, // エフェクトコンパイルオプション(0推奨)
&vsBlob, // 受け取る為のポインタのアドレス
&errorBlob // エラー時はerrorBlobにメッセージが入る
);
if (FAILED(result))
{
if (result == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
::OutputDebugStringA("VSファイルが見当たりません");
}
else
{
std::string errstr;
errstr.resize(errorBlob->GetBufferSize());
std::copy_n((char*)errorBlob->GetBufferPointer(), errorBlob->GetBufferSize(), errstr.begin());
errstr += "\n";
OutputDebugStringA(errstr.c_str());
}
exit(1); // 行儀悪い、らしい
}
result = D3DCompileFromFile
(
L"BasicPixelShader.hlsl", // シェーダー名
nullptr, // defineはなし
D3D_COMPILE_STANDARD_FILE_INCLUDE, // インクルードはデフォルト
"BasicPS", "ps_5_0", // 関数はBasicVS、対象シェーダーはvs_5_0
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, // デバック用および最適化なし
0, // エフェクトコンパイルオプション(0推奨)
&psBlob, // 受け取る為のポインタのアドレス
&errorBlob // エラー時はerrorBlobにメッセージが入る
);
if (FAILED(result))
{
if (result == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
::OutputDebugStringA("PSファイルが見当たりません");
}
else
{
std::string errstr;
errstr.resize(errorBlob->GetBufferSize());
std::copy_n((char*)errorBlob->GetBufferPointer(), errorBlob->GetBufferSize(), errstr.begin());
errstr += "\n";
OutputDebugStringA(errstr.c_str());
}
exit(1);
}
// 頂点レイアウト
D3D12_INPUT_ELEMENT_DESC inputLayout[] =
{
{
"POSITION", // セマンティック名
0, // 同じセマンティクス名の時に使うインデックス
DXGI_FORMAT_R32G32B32_FLOAT, // フォーマット(要素数とビット数で型を現す)
0, // 入力スロットインデックス
D3D12_APPEND_ALIGNED_ELEMENT, // データのオフセット位置
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, //
0 // 一度に描画するインスタンスの数
},
{
"NORMAL",
0,
DXGI_FORMAT_R32G32_FLOAT,
0,
D3D12_APPEND_ALIGNED_ELEMENT,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
0
},
{
"TEXCOORD",
0,
DXGI_FORMAT_R32G32_FLOAT,
0,
D3D12_APPEND_ALIGNED_ELEMENT,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
0
},
{
"BONE_NO",
0,
DXGI_FORMAT_R16G16_UINT,
0,
D3D12_APPEND_ALIGNED_ELEMENT,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
0
},
{
"WEIGHT",
0,
DXGI_FORMAT_R8_UINT,
0,
D3D12_APPEND_ALIGNED_ELEMENT,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
0
},
{
"EDGE_FLG",
0,
DXGI_FORMAT_R8_UINT,
0,
D3D12_APPEND_ALIGNED_ELEMENT,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
0
},
};