XNA .Fbxt纹理

时间:2009-11-19 19:10:36

标签: xna textures shader

我在XNA中使用带有自定义着色器的标准.fbx导入程序。 .fbx模型正确地进行了UV包装,并在使用BasicEffect时进行了适当的纹理处理。但是,当我使用自定义效果时,我必须将纹理作为参数加载,并且未正确映射。

问题:1)如何使用包含的纹理坐标和自定义效果正确地纹理我的.fbx模型? 2)有没有办法从加载的.fbx模型对象访问纹理?这个纹理在哪里?

注意:我研究过自定义内容管道,并且不相信编写我自己的Fbx导入器/处理器会很有效。但是,如果有人可以描述性地为我提供这方面的第一手经验,那么我将使用自定义管道。

感谢您抽出宝贵时间阅读本文。

2 个答案:

答案 0 :(得分:6)

这是一个老问题,但我必须在昨天自己解决这个问题,所以我想我会发布一个后续内容:

如果您使用默认的FBX内容处理器并将DefaultEffect属性设置为BasicEffect,则可以通过以下方式获取对象的Texture2D

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

请注意,模型中的每个网格可能具有不同的纹理。

纹理坐标与位置等一起存储在MeshPart的{​​{1}}中。我见过两个顶点声明。对于使用单个纹理(3DS Max中的位图材质)的模型/网格,顶点声明为VertexBuffer

对于具有两个纹理(位图和不透明度/ alpha贴图)的模型,声明具有以下元素:

VertexPositionNormalTexture

或包裹在Position Normal Texture (usage index 0) Texture (usage index 1) 结构中

IVertexType

和等效的HLSL结构:

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; }
    }
}

请注意,在我发布此消息之前,我已将struct VertexPositionNormalTextureTexture { float3 Position : POSITION0; float3 Normal : NORMAL0; float4 Texture0 : TEXCOORD0; float4 Texture1 : TEXCOORD1; }; .Position.NormalVector4更改为Vector3float4测试了它。可能需要将它们更改回float3Vector4

当然,您需要在像素着色器中使用采样器和一些基本逻辑来读取每个纹理。假设您已将两个效果参数xTexture0和xTexture1设置为包含颜色纹理和不透明度贴图的float4个对象,

Texture2D

这是一个简单的双纹理像素着色器。如果您只想要一个纹理,只需从第一个采样器读取并返回值,或应用光照等。

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

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

这里的相关点是纹理坐标已经存在于FBX中并且已经存储在每个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; } 的{​​{1}}中,所以你需要做的就是提取纹理,传递它作为全局效果参数进入着色器,并照常进行。

答案 1 :(得分:1)

它不起作用的原因是因为你必须手动设置效果的参数而不是依赖于basiceffect(它会在内容管道中设置着色器参数)。现在,我不熟悉你的着色器,所以我无法开出代码来解决你的问题......

要回答你的第二个问题,你可以用迂回的方式绕过它。由于默认情况下模型在内容管道中加载basiceffect,因此导入纹理并将其分配给管道中着色器的 参数。因此,如果要访问它,则必须查看modelmeshpart的默认效果属性。 Here是一个描述此过程的论坛帖子。

更正确的答案是完全自定义导入器与仅使用默认值之间的折衷。您可以创建一个继承自现有模型的自定义模型处理器。在那里,您可以导入自己的自定义效果,以及自定义纹理和您需要设置的任何参数。并将其设置在modelcontent上。有一篇文章(无论是在Shawn Hargreave的博客上,还是在msdn上)都展示了如何做到这一点,但遗憾的是我现在还没有找到它。

祝你好运!