差分
ナビゲーションに移動
検索に移動
編集の要約なし
[[ハードウェアインスタンシング]]を利用するにあたりMatrix型の[[World座標]]を渡したい。
つまり[[C♯]]から[[HLSL]]にMatrix型を渡せると嬉しい。
しかし[[HLSL]]に渡すデータ型を示すVertexElementFormatは「Vector4」が最大となっている。
Matrixは渡せない。
そこでMatrixはfloat4x4であり単純に4倍と仮定してVector4を4個ズラズラ列べる。
VertexElementUsageはfloat4型のセマンティクス、かつ誰も使ってないであろうBlendWeightを指定した。
<syntaxhighlight lang="csharp">
// 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);
</syntaxhighlight>
HLSL側はfloat4が4個で受け取り、シェーダー関数内でmatrixに合成している。
<syntaxhighlight lang="hlsl">
// 「float4が4個」として受け取る。
struct InstanceInput
{
float4 w1 : BLENDWEIGHT0;
float4 w2 : BLENDWEIGHT1;
float4 w3 : BLENDWEIGHT2;
float4 w4 : BLENDWEIGHT3;
};
VertexShaderOutput MainVS(VertexShaderInput input, InstanceInput instance)
{
VertexShaderOutput output = (VertexShaderOutput)0;
// 「float4が4個」をmatrixにする。
matrix world = matrix(instance.w1, instance.w2, instance.w3, instance.w4);
// 〜以下略〜
return output;
}
</syntaxhighlight>
とりあえず正常に動いている。
== 関連項目 ==
* [[MonoGameでプログラマブルシェーダーを使う]]
* [[MonoGameでハードウェアインスタンシングしてみる]]
* [[MonoGameでピクセルシェーダーを使ってテクスチャを貼る]]
* [[Metalでテクスチャから補正せずにサンプリングする]]
* [[HLSLでGaussian Blur]]
[[category: MonoGame]]
[[category: HLSL]]
つまり[[C♯]]から[[HLSL]]にMatrix型を渡せると嬉しい。
しかし[[HLSL]]に渡すデータ型を示すVertexElementFormatは「Vector4」が最大となっている。
Matrixは渡せない。
そこでMatrixはfloat4x4であり単純に4倍と仮定してVector4を4個ズラズラ列べる。
VertexElementUsageはfloat4型のセマンティクス、かつ誰も使ってないであろうBlendWeightを指定した。
<syntaxhighlight lang="csharp">
// 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);
</syntaxhighlight>
HLSL側はfloat4が4個で受け取り、シェーダー関数内でmatrixに合成している。
<syntaxhighlight lang="hlsl">
// 「float4が4個」として受け取る。
struct InstanceInput
{
float4 w1 : BLENDWEIGHT0;
float4 w2 : BLENDWEIGHT1;
float4 w3 : BLENDWEIGHT2;
float4 w4 : BLENDWEIGHT3;
};
VertexShaderOutput MainVS(VertexShaderInput input, InstanceInput instance)
{
VertexShaderOutput output = (VertexShaderOutput)0;
// 「float4が4個」をmatrixにする。
matrix world = matrix(instance.w1, instance.w2, instance.w3, instance.w4);
// 〜以下略〜
return output;
}
</syntaxhighlight>
とりあえず正常に動いている。
== 関連項目 ==
* [[MonoGameでプログラマブルシェーダーを使う]]
* [[MonoGameでハードウェアインスタンシングしてみる]]
* [[MonoGameでピクセルシェーダーを使ってテクスチャを貼る]]
* [[Metalでテクスチャから補正せずにサンプリングする]]
* [[HLSLでGaussian Blur]]
[[category: MonoGame]]
[[category: HLSL]]