プログラミング 複数テクスチャ使ったインスタンシングがわからねぇ・・・orz
あいさつ
どうも、はかせです。
今回は以前作った弾幕シューティングを改造しようとして詰まった話です。
改造しようと思った理由
理由はこのツイートをご覧ください。
xmlデータ管理をちゃんと作ろうと思う
— hakase@プログラミングなんもわからん (@hakase70945250) 2019年6月24日
↓
じゃなんかゲーム作ろう
↓
そいやクオリティ低い弾幕ゲーがあったな改造しよう
↓
せっかくだしインスタンシングつけよう
↓
複数テクスチャ使ったインスタンシングのやり方がわかんねぇ←今ここ
今の私のすべてがこのツイートに凝縮されています。
それでは今回はこの辺でノシ
・・・・・
とはいきませんねw
ちゃんと説明します。
前回までである程度c++でxmlを扱うノウハウを得ました。
なので実際に使ってみようと思ったわけです。
頭の中から妄想で状況とデータを出してもいいんですが、
どうせなら以前作った弾幕シューティングを改造してみようと思ったわけです。
(クオリティがお察しだったからね)
hakase0274.hatenablog.com
それでどうせ改造するなら徹底的にってことで、
インスタンシングも使ってみようと思ったわけです。
弾幕ですから効果絶大でしょうしね。
ただここで問題が発生します。
私が前やったインスタンシングは
プリミティブもしくは単一テクスチャを増産するものでした。
なのでテクスチャが一種類なら問題ないんですが、
複数扱うとなると色々うまくいきません(´;ω;`)
とりあえず愚痴るだけじゃ仕方ないんで
今の進捗を。
まずは一種類のテクスチャをインスタンシングです。
void DXManager::RenderInstancing() { mDeviceContext->VSSetShader(mVertexShader.Get(), NULL, 0); mDeviceContext->PSSetShader(mPixelShader.Get(), NULL, 0); // パラメータの受け渡し D3D11_MAPPED_SUBRESOURCE pdata; mDeviceContext->Map(mPerInstanceBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &pdata); PerInstanceData* instanceData = (PerInstanceData*)(pdata.pData); float defaultYPos = 1.5f; float offset = 0.11f; int oneLineNum = 10; for (int i = 0; i < mInstanceNum ; i++) { //とりあえずループ変数使って移動 float xPos = i % oneLineNum * offset - 2.0f; float yPos = defaultYPos - (i / oneLineNum * offset); XMMATRIX move = XMMatrixTranslation(xPos, yPos, 1.0f); //行列情報をセット instanceData[i].matrix = XMMatrixTranspose(mScale * mRotation * move * mView * mProj); //色情報をセット instanceData[i].color = XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f); } mDeviceContext->Unmap(mPerInstanceBuffer.Get(), 0); mDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); mDeviceContext->VSSetShaderResources(0, 1, mShaderResourceView.GetAddressOf()); ID3D11ShaderResourceView* srv[] = { mShaderResourceView.Get() ,mTextureShaderResourceView1.Get()}; mDeviceContext->PSSetShaderResources(0, 2,srv); // 描画実行 mDeviceContext->DrawIndexedInstanced(mDrawNum, mInstanceNum, 0, 0, 0); }
以前と違うのはテクスチャ用のShaderResourceViewが追加されてってとこですね。
問題ありません。
では二種類目のテクスチャを用意して
その隣にある領域に出してみたいです。
void DXManager::RenderInstancing() { //・・・さっきのコード省略 mDeviceContext->Map(mPerInstanceBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &pdata); for (int i = 0; i < mInstanceNum; i++) { //とりあえずループ変数使って移動 float xPos = i % oneLineNum * offset - 1.0f; float yPos = defaultYPos - (i / oneLineNum * offset); XMMATRIX move = XMMatrixTranslation(xPos, yPos, 1.0f); //行列情報をセット instanceData[i].matrix = XMMatrixTranspose(mScale * mRotation * move * mView * mProj); //色情報をセット instanceData[i].color = XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f); } mDeviceContext->Unmap(mPerInstanceBuffer.Get(), 0); mDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); mDeviceContext->VSSetShaderResources(0, 1, mShaderResourceView.GetAddressOf()); ID3D11ShaderResourceView* srv2[] = { mShaderResourceView.Get() ,mTextureShaderResourceView2.Get() }; mDeviceContext->PSSetShaderResources(0, 2, srv2); // 描画実行 mDeviceContext->DrawIndexedInstanced(mDrawNum, mInstanceNum, mDrawNum, 0, 0); }
そのまんまスライドしちゃった!?
・・・・・・・・・
まぁシェーダーに渡していたバッファを
Map/Unmapで直接書き換えているのでわからなくはないですが、
これはなかなかきついですね・・・
あとがき
今回は以前作った弾幕を改造しようと
最近勉強したことをつぎ込もうとしたら
勉強不足だった話でした。
やっぱ実際に使ってみようとしないと
実際にハマる穴に落ちないですねw
またあーでもないこーでもないって頭悩ましつつ、
色んなサイトめぐって解決策探します。
それでは今回はこの辺でノシ