「MonoGameでHLSLにMatrixを渡す」の版間の差分
Administrator (トーク | 投稿記録) |
Administrator (トーク | 投稿記録) |
||
(同じ利用者による、間の1版が非表示) | |||
34行目: | 34行目: | ||
<syntaxhighlight lang="hlsl"> | <syntaxhighlight lang="hlsl"> | ||
// 「float4が4個」として受け取る。 | // 「float4が4個」として受け取る。 | ||
− | struct | + | struct VSInstance |
{ | { | ||
float4 w1 : BLENDWEIGHT0; | float4 w1 : BLENDWEIGHT0; | ||
42行目: | 42行目: | ||
}; | }; | ||
− | + | VSOutput VSMain(VSInput input, VSInstance instance) | |
{ | { | ||
− | + | VSOutput output = (VSOutput)0; | |
// 「float4が4個」をmatrixに合成する。 | // 「float4が4個」をmatrixに合成する。 | ||
50行目: | 50行目: | ||
// 〜以下略〜 | // 〜以下略〜 | ||
+ | |||
return output; | return output; | ||
} | } |
2020年6月10日 (水) 01:50時点における最新版
ハードウェアインスタンシングを利用するにあたりC♯からHLSLにMatrix型のWorld座標をバーテックスバッファ経由で渡したい。
しかしMonoGameからHLSLに渡す際にデータ型を明示するVertexElementFormatは「Vector4」が最大となっている。Matrix型はない。
そこで「MatrixはVector4が4個セットになったもの」と仮定してVector4を4個ズラズラ列べてみる。VertexElementUsageはfloat4型のセマンティクス、かつ誰も使ってないであろうBlendWeightを指定した。
// Matrix型のワールド座標
// 詳細は略
var instances = new Matrix[10];
// VertexElementFormatで一番大きい型はVector4(float4)となっている。
// Matrix(float4x4)はない。
// 仕方がないので「Vector4が4個」と指定する。
var vertexDeclaration = new VertexDeclaration(
new VertexElement( 0, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 0),
new VertexElement(16, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 1),
new VertexElement(32, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 2),
new VertexElement(48, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 3));
// ダイナミックバーテックスバッファーを生成する
var instanceBuffer = new DynamicVertexBuffer(
GraphicsDevice,
vertexDeclaration,
instances.Length,
BufferUsage.WriteOnly);
// MatrixのままSetDataして問題ない。
instanceBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard);
HLSL側は「float4が4個」として受け取り、バーテックスシェーダー内でmatrixに合成している。
// 「float4が4個」として受け取る。
struct VSInstance
{
float4 w1 : BLENDWEIGHT0;
float4 w2 : BLENDWEIGHT1;
float4 w3 : BLENDWEIGHT2;
float4 w4 : BLENDWEIGHT3;
};
VSOutput VSMain(VSInput input, VSInstance instance)
{
VSOutput output = (VSOutput)0;
// 「float4が4個」をmatrixに合成する。
matrix world = matrix(instance.w1, instance.w2, instance.w3, instance.w4);
// 〜以下略〜
return output;
}
とりあえず正常に動いている。