这是一个旧问题,但昨天我不得不自己解决,所以我想发表一篇后续文章:
如果您正在使用默认的FBX内容处理器,并且将DefaultEffect
属性设置为BasicEffect
,则可以通过以下方式获取对象的Texture2D
:
texture = ((BasicEffect)model.Meshes[0].Effects[0]).Texture;
请注意,模型中的每个网格可能具有不同的纹理。
纹理坐标与位置等一起存储在MeshPart的VertexBuffer中。我看到了两个顶点声明。对于使用单一纹理(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
pixel = float4(0,1,0,1);
return pixel;
}
这里的关键点是纹理坐标已经存在于FBX中,并已存储在每个MeshPart
的VertexBuffer
中,因此您只需要提取纹理,将其作为全局效果参数传递到您的着色器中,并像往常一样继续进行。