这是一个老问题,但我昨天必须自己解决这个问题,所以我想我会发布一个跟进:
如果您使用默认的 FBX 内容处理器并将DefaultEffect 属性设置为BasicEffect,您可以通过以下方式获取对象的Texture2D:
texture = ((BasicEffect)model.Meshes[0].Effects[0]).Texture;
请注意,模型中的每个网格可能具有不同的纹理。
纹理坐标与位置等一起存储在MeshPart'sVertexBuffer 中。我见过两个顶点声明。对于使用单个纹理(3DS Max 中的位图材质)的模型/网格,顶点声明为 VertexPositionNormalTexture。
对于具有两个纹理(一个位图和一个不透明度/alpha 映射)的模型,声明包含以下元素:
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中并且已经存储在每个MeshPart的VertexBuffer中,所以你需要做的就是提取纹理,将它传递给你的着色器一个全局效果参数,然后照常进行。