3

XNA のカスタム シェーダーで標準の .fbx インポーターを使用しています。.fbx モデルは適切に UV ラップされ、BasicEffect を使用すると適切にテクスチャリングされます。ただし、カスタム エフェクトを使用する場合、テクスチャをパラメータとしてロードする必要があり、正しくマッピングされません。

質問: 1) 含まれているテクスチャの座標をカスタム エフェクトで使用して、.fbx モデルを適切にテクスチャ化するにはどうすればよいですか? 2) ロードされた .fbx モデル オブジェクトからテクスチャにアクセスする方法はありますか? このテクスチャはどこに行きますか?

注: 私はカスタム コンテンツ パイプラインを研究しましたが、独自の Fbx インポーター/プロセッサを作成することが効率的であるとは考えていません。ただし、誰かがこれが答えであるという直接の経験を説明的に提供できる場合は、カスタム パイプラインを使用します。

お時間をいただき、この投稿を読んでいただきありがとうございます。

4

2 に答える 2

6

これは古い質問ですが、昨日自分でこれを理解しなければならなかったので、フォローアップを投稿すると思いました:

デフォルトの FBX コンテンツ プロセッサを使用していて、DefaultEffectプロパティが に設定されている場合は、次の方法でオブジェクトBasicEffectの を取得できます。Texture2D

texture = ((BasicEffect)model.Meshes[0].Effects[0]).Texture;

モデル内の各メッシュのテクスチャが異なる場合があることに注意してください。

テクスチャ座標は、位置などとともに に格納されます。2 つの頂点宣言を見てきましたMeshPartVertexBuffer単一のテクスチャ (3DS Max のビットマップ マテリアル) を使用したモデル/メッシュの場合、頂点宣言はVertexPositionNormalTexture.

2 つのテクスチャ (ビットマップと不透明度/アルファ マップ) を持つモデルの場合、宣言には次の要素が含まれます。

Position
Normal
Texture (usage index 0)
Texture (usage index 1)

または、IVertexType構造にラップされ、

public struct VertexPositionNormalTextureTexture : IVertexType
{
    public Vector3 Position;
    public Vector3 Normal;
    public Vector4 Texture0;
    public Vector4 Texture1;

    public static VertexDeclaration VertexDeclaration
    {
        get
        {
            return new VertexDeclaration
            (
            new VertexElement(0,VertexElementFormat.Vector3, VertexElementUsage.Position, 0)
            ,
            new VertexElement(0,VertexElementFormat.Vector3, VertexElementUsage.Normal, 0)
            ,
            new VertexElement(0,VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 0)
            ,
            new VertexElement(0,VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 1)
            );
        }
    }


    VertexDeclaration IVertexType.VertexDeclaration
    {
        get { return VertexDeclaration; }
    }
}

および同等の HLSL 構造:

struct VertexPositionNormalTextureTexture
{
    float3 Position : POSITION0;
    float3 Normal : NORMAL0;
    float4 Texture0 : TEXCOORD0;
    float4 Texture1 : TEXCOORD1;
};

.Positionこれを投稿する前にand .NormalfromVector4Vector3tofloat4を変更しfloat3、テストしていないことに注意してください。Vector4およびに戻す必要がある可能性がありfloat4ます。

もちろん、各テクスチャを読み取るには、ピクセル シェーダーにサンプラーといくつかの基本的なロジックが必要です。Texture2Dカラー テクスチャと不透明度マップを含むオブジェクトに 2 つのエフェクト パラメータ xTexture0 と xTexture1 を設定したと仮定すると、

// texture sampler
sampler Sampler0 = sampler_state
{
    Texture = (xTexture0);
};

sampler Sampler1 = sampler_state
{
    Texture = (xTexture1);
};

これは単純な 2 テクスチャ ピクセル シェーダーです。テクスチャが 1 つだけ必要な場合は、最初のサンプラーから読み取って値を返すか、ライティングなどを適用します。

float4 TwoTexturePixelShader(VertexPositionNormalTextureTexture input) : COLOR0
{
    float4 texel0;
    float4 texel1;
    float4 pixel;

    // check global effect parameter to see if we want textures turned on
    // (useful for debugging geometry weirdness)
    if (TexturesEnabled)
    {
        texel0 = tex2D(Sampler0, input.Texture0);
        texel1 = tex2D(Sampler1, input.Texture1);       
        /// Assume texel1 is an alpha map, so just multiple texel0 by that alpha.
        pixel.rgb=texel0.rgb;
        pixel.a=texel0.a;
    }
    else
        /// return 100% green
        pixel = float4(0,1,0,1);

    return pixel;

} 

ここで重要なのは、テクスチャ座標が既に FBX に存在し、それぞれMeshPartのにすでに保存されVertexBufferていることです。そのため、テクスチャを抽出し、それをグローバル エフェクト パラメータとしてシェーダに渡し、通常どおり処理を進めるだけです。 .

于 2011-03-24T16:36:27.333 に答える
1

これが機能しない理由は、basiceffect (コンテンツ パイプラインでシェーダー パラメーターが設定されている) に依存するのではなく、エフェクトのパラメーターを手動で設定する必要があるためです。さて、私はあなたのシェーダーに精通していないので、あなたの問題を解決するためのコードを処方できませんでした...

2 番目の質問に答えるには、回り道のような方法で回避できます。モデルはデフォルトで basiceffect を使用してコンテンツ パイプラインに読み込まれるため、テクスチャがインポートされ、パイプラインのシェーダーのパラメーターに割り当てられます。したがって、アクセスしたい場合は、modelmeshpart のデフォルトのエフェクト プロパティを確認する必要があります。これは、このプロセスを説明するフォーラムの投稿です。

より正しい答えは、完全なカスタム インポーターとデフォルトのみの使用との間の妥協です。既存のものから継承するカスタム モデル プロセッサを作成できます。そこでは、独自のカスタム エフェクト、カスタム テクスチャ、および設定が必要なパラメータをインポートできます。モデルコンテンツに設定します。これを行う方法を示す記事 (Shawn Hargreave のブログまたは msdn のいずれか) がありましたが、残念ながら現時点では見つけられません。

幸運を!

于 2009-12-04T14:10:28.233 に答える