「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;
}

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

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