2009-11-19 5 views
3

J'utilise l'importateur .fbx standard avec des shaders personnalisés dans XNA. Le modèle .fbx est correctement enveloppé UV et est texturé de manière appropriée lorsque j'utilise BasicEffect. Cependant, lorsque j'utilise mon effet personnalisé, je dois charger la texture en tant que paramètre, et elle n'est pas mappée correctement. Questions: 1) Comment puis-je texturer correctement mon modèle .fbx en utilisant les coordonnées de la texture incluse avec des effets personnalisés? 2) Existe-t-il un moyen d'accéder à la texture à partir de l'objet de modèle .fbx chargé? Où va cette texture?XNA .Fbx textures

Remarque: J'ai étudié des pipelines de contenu personnalisés et je ne crois pas que l'écriture de mon propre importateur/processeur Fbx sera efficace. Cependant, si quelqu'un peut me fournir de façon descriptive une expérience de première main de cette réponse que je vais utiliser le pipeline personnalisé.

Nous vous remercions de votre temps et de la lecture de cet article.

Répondre

6

Ceci est une vieille question, mais je devais comprendre cela moi-même hier, donc je pensais que je poste un suivi:

Si vous utilisez le processeur contenu par défaut FBX et ont la propriété DefaultEffect mis à BasicEffect, vous pouvez obtenir le Texture2D de l'objet via:

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

Notez que la chaque maille dans le modèle peut avoir une texture différente.

Les coordonnées de texture sont stockées dans le MeshPartVertexBuffer avec la position, etc. J'ai vu deux déclarations de vertex. Pour un modèle/maillage utilisant une seule texture (matériau bitmap dans 3DS Max), la déclaration de vertex était VertexPositionNormalTexture.

Pour un modèle qui avait deux textures (un bitmap et une carte d'opacité/alpha), la déclaration avait les éléments:

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

ou, enveloppé dans une structure 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; } 
    } 
} 

et la structure HLSL équivalente:

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

Notez que j'ai changé .Position et .Normal de Vector4 et Vector3 à float4 et float3 avant que j'ai posté ceci, et ne l'ai pas testé. Il est possible qu'ils doivent être remplacés par Vector4 et float4.

Bien sûr, vous aurez besoin d'un échantillonneur et d'une logique de base dans votre pixel shader pour lire chaque texture. En supposant que vous avez défini deux paramètres d'effet xTexture0 et xTexture1 à Texture2D objets contenant votre texture de couleur et carte d'opacité,

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

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

et est ici d'un simple pixel shader deux texture. Si vous voulez une seule texture, juste de lire à partir du premier sampler et retourner la valeur, ou appliquer l'éclairage, etc.

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; 

} 

Les points pertinents ici sont que les coordonnées de texture sont déjà présentes dans le FBX et sont déjà stockés Dans chaque MeshPartVertexBuffer, tout ce que vous avez à faire est d'extraire la texture, de la passer dans votre shader en tant que paramètre d'effet global et de continuer normalement.

1

La raison pour laquelle cela ne fonctionne pas est que vous devez définir les paramètres de l'effet manuellement au lieu de vous baser sur l'effet de base (qui aurait eu les paramètres de shader définis dans le pipeline de contenu). Maintenant, je ne suis pas familier avec votre shader, donc je ne pouvais pas prescrire de code pour résoudre votre problème ...

Pour répondre à votre deuxième question, vous pouvez contourner le problème de façon indirecte. Étant donné que le modèle est chargé dans le pipeline de contenu avec basiceffect par défaut, la texture est importée et affectée aux paramètres du shader à l'intérieur du pipeline. Donc, si vous voulez y accéder, vous devez regarder la propriété d'effet par défaut de modelmeshpart. Here est un message de forum qui décrit ce processus.

La réponse la plus correcte serait un compromis entre un importateur complet sur mesure et l'utilisation de la valeur par défaut. Vous pouvez créer un modelprocesseur personnalisé héritant de celui existant. Là, vous pouvez importer votre propre effet personnalisé, avec vos textures personnalisées et tous les paramètres que vous devez définir. et placez-le sur le contenu du modèle. Il y avait un article (soit sur le blog de Shawn Hargreave, soit sur msdn) qui montrait comment faire cela, mais je n'arrive pas à le trouver pour le moment malheureusement.

bonne chance!

+0

Est-ce le processus que vous utiliseriez pour reproduire les effets de 3DS max dans le fichier FBX? –

+0

Oui, il est ...... –

+0

(au cas où quelqu'un viendrait à travers cela et en a besoin) l'échantillon Skinned Effect pour GS 3.1 (avant qu'ils introduisent le stock SkinEffect) [http://create.msdn.com/fr US/education/catalog/sample/skinned_model] montre comment changer BasicEffect pour un shader personnalisé chargé au moment du design. (La méthode ConvertMaterial) – sebf