「MonoGameでHLSLにMatrixを渡す」の版間の差分

提供: MonoBook
ナビゲーションに移動 検索に移動
 
(同じ利用者による、間の5版が非表示)
1行目: 1行目:
 
[[ハードウェアインスタンシング]]を利用するにあたり[[C♯]]から[[HLSL]]にMatrix型の[[World座標]]を[[バーテックスバッファ]]経由で渡したい。
 
[[ハードウェアインスタンシング]]を利用するにあたり[[C♯]]から[[HLSL]]にMatrix型の[[World座標]]を[[バーテックスバッファ]]経由で渡したい。
  
しかしMonoGameでは[[HLSL]]に渡すデータ型を示すVertexElementFormatは「Vector4」が最大となっており、Vector4が4個セットになっているMatrix型は渡せない。
+
しかしMonoGameから[[HLSL]]に渡す際にデータ型を明示するVertexElementFormatは「Vector4」が最大となっている。Matrix型はない。
  
そこでMatrixはVector4の4倍と仮定してVector4を4個ズラズラ列べる。
+
そこで「MatrixはVector4が4個セットになったもの」と仮定してVector4を4個ズラズラ列べてみる。VertexElementUsageはfloat4型のセマンティクス、かつ誰も使ってないであろうBlendWeightを指定した。
VertexElementUsageはfloat4型のセマンティクス、かつ誰も使ってないであろうBlendWeightを指定した。
 
  
 
<syntaxhighlight lang="csharp">
 
<syntaxhighlight lang="csharp">
16行目: 15行目:
 
// 仕方がないので「Vector4が4個」と指定する。
 
// 仕方がないので「Vector4が4個」と指定する。
 
var vertexDeclaration = new VertexDeclaration(
 
var vertexDeclaration = new VertexDeclaration(
        new VertexElement( 0, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 0),
+
    new VertexElement( 0, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 0),
        new VertexElement(16, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 1),
+
    new VertexElement(16, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 1),
        new VertexElement(32, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 2),
+
    new VertexElement(32, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 2),
        new VertexElement(48, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 3));
+
    new VertexElement(48, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 3));
  
 
// ダイナミックバーテックスバッファーを生成する
 
// ダイナミックバーテックスバッファーを生成する
32行目: 31行目:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
HLSL側はfloat4が4個で受け取り、シェーダー関数内でmatrixに合成している。
+
HLSL側は「float4が4個」として受け取り、[[バーテックスシェーダー]]内でmatrixに合成している。
 
<syntaxhighlight lang="hlsl">
 
<syntaxhighlight lang="hlsl">
 
// 「float4が4個」として受け取る。
 
// 「float4が4個」として受け取る。
struct InstanceInput
+
struct VSInstance
 
{
 
{
float4 w1 : BLENDWEIGHT0;
+
    float4 w1 : BLENDWEIGHT0;
float4 w2 : BLENDWEIGHT1;
+
    float4 w2 : BLENDWEIGHT1;
float4 w3 : BLENDWEIGHT2;
+
    float4 w3 : BLENDWEIGHT2;
float4 w4 : BLENDWEIGHT3;
+
    float4 w4 : BLENDWEIGHT3;
 
};
 
};
  
VertexShaderOutput MainVS(VertexShaderInput input, InstanceInput instance)
+
VSOutput VSMain(VSInput input, VSInstance instance)
 
{
 
{
     VertexShaderOutput output = (VertexShaderOutput)0;
+
     VSOutput output = (VSOutput)0;
  
// 「float4が4個」をmatrixにする。
+
    // 「float4が4個」をmatrixに合成する。
matrix world = matrix(instance.w1, instance.w2, instance.w3, instance.w4);
+
    matrix world = matrix(instance.w1, instance.w2, instance.w3, instance.w4);
  
 
     // 〜以下略〜
 
     // 〜以下略〜
 +
 
     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;
}

とりあえず正常に動いている。

関連項目[編集 | ソースを編集]