2009-11-19 2 views
3

Я использую стандартный импортер .fbx с пользовательскими шейдерами в XNA. Модель .fbx UV обернута правильно и текстурирована соответствующим образом, когда я использую BasicEffect. Однако, когда я использую свой собственный эффект, мне приходится загружать текстуру в качестве параметра, и она не отображается правильно.XNA .Fbx текстуры

Вопросы: 1) Как правильно текстурировать мою .fbx-модель, используя координаты встроенной текстуры с пользовательскими эффектами? 2) Есть ли способ получить доступ к текстуре из загруженного объекта модели .fbx? Куда идет эта текстура?

Примечание. Я изучил конвейеры контентов и не верю, что мой собственный импортер/процессор Fbx будет эффективен. Однако, если кто-то может описательно предоставить мне опыт из первых рук, это будет ответом, чем я буду использовать настраиваемый конвейер.

Спасибо за ваше время и за чтение этого сообщения.

ответ

6

Это старый вопрос, но я должен был понять это сам вчера, так что я думал, что я оставить Followup:

Если вы используете процессор содержимого по умолчанию FBX и имеют DefaultEffect свойство установлено в BasicEffect, вы можете получить Texture2D для объекта с помощью:

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

Обратите внимание, что каждая сетка в модели может иметь различную текстуру.

Координаты текстуры хранятся в MeshPartVertexBuffer вместе с положением и т. Д. Я видел две объявления вершин. Для модели/сетки, которая использовала одну текстуру (растровый материал в 3DS Max), объявление вершины было VertexPositionNormalTexture.

Для модели, которая имела две текстуры (растровое изображение и непрозрачность/альфа-карта), декларация имела элементы:

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 и .Normal от Vector4 и Vector3 до float4 и float3, прежде чем я разместил это и не протестировал его. Возможно, что их, возможно, придется заменить на Vector4 и float4.

Конечно, вам понадобится пробоотборник и некоторая базовая логика в вашем пиксельном шейдере для чтения каждой текстуры. Предполагая, что вы установили два параметра эффекта xTexture0 и xTexture1 к Texture2D объектов, содержащих цветовую текстуру и карту непрозрачности,

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

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

и вот два простых текстур пиксельных шейдеров. Если вы хотите только одну текстуру, только что прочитал с первого пробоотборника и возвращает значение, или применить освещение и т.д.

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 и уже сохранены в каждом MeshPartVertexBuffer, так что все, что вам нужно сделать, это извлечь текстуру, передать ее в ваш шейдер в качестве глобального параметра эффекта и продолжить как обычно.

1

Причина, по которой она не работает, заключается в том, что вы должны вручную установить параметры эффекта вместо того, чтобы полагаться на basiceffect (который имел бы параметры шейдера, заданные в конвейере содержимого). Теперь я не знаком с вашим шейдером, поэтому я не мог прописать код, чтобы решить вашу проблему ...

Чтобы ответить на второй вопрос, вы можете обойти его круговым способом. Поскольку модель загружается по конвейеру контента с помощью basiceffect по умолчанию, текстура импортируется и присваивается параметрам шейдера внутри конвейера. Поэтому, если вы хотите получить к нему доступ, вам придется посмотреть свойство свойства modelmeshpart по умолчанию. Here - это сообщение в форуме, которое описывает этот процесс.

Более правильным ответом будет компромисс между полным пользовательским импортером и просто использованием значения по умолчанию. Вы можете создать собственный модельный процессор, который наследуется от существующего. Там вы можете импортировать свой собственный эффект, наряду с вашими настраиваемыми текстурами и любыми параметрами, которые вам нужно установить. и установить его на modelcontent. Была статья (либо в блоге Shawn Hargreave, либо на msdn), которая показывала, как это сделать, но я не могу найти ее в настоящий момент, к сожалению.

удачи!

+0

Это процесс, который вы использовали бы для воспроизведения эффектов от 3DS max в файле FBX? –

+0

Да, это ... –

+0

(в случае, если кто-то приходит навстречу этому и нуждается в нем) образец Skinned Effect для GS 3.1 (до того, как они ввели акцию SkinnedEffect) [http://create.msdn.com/en- US/education/catalog/sample/skinned_model] показывает, как заменить BasicEffect для пользовательского шейдера, загруженного во время разработки. (Метод ConvertMaterial) – sebf

Смежные вопросы