XNA .Fbx 纹理

发布于 2024-08-12 01:21:16 字数 319 浏览 4 评论 0原文

我在 XNA 中使用标准 .fbx 导入器和自定义着色器。当我使用 BasicEffect 时,.fbx 模型经过正确的 UV 包裹并具有适当的纹理。但是,当我使用自定义效果时,我必须将纹理作为参数加载,并且它未正确映射。

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

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

感谢您花时间阅读这篇文章。

I'm using the standard .fbx importer with custom shaders in XNA. The .fbx model is UV wrapped properly and is textured appropriately when I use BasicEffect. However when I use my custom effect I have to load the texture in as a parameter, and it is not mapped correctly.

Questions: 1) How can I texture my .fbx model properly using the included texture's coordinates with custom effects? 2) Is there a way to access the texture from the loaded .fbx model object? Where does this texture go?

Note: I've studied custom content pipelines and don't believe writing my own Fbx importer/processor will be efficient. However if someone can descriptively supply me with firsthand experience of this being the answer than I will use the custom pipeline.

Thank you for your time and for reading this post.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情感失落者 2024-08-19 01:21:16

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

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

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

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

纹理坐标与位置等一起存储在 MeshPartVertexBuffer 中。我看到了两个顶点声明。对于使用单个纹理(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;
};

请注意,我更改了 < code>.Position 和 .NormalVector4Vector3float4float3 在我发布此内容之前,尚未对其进行测试。它们可能需要改回 Vector4float4

当然,您需要一个采样器和像素着色器中的一些基本逻辑来读取每个纹理。假设您已将两个效果参数 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< /code> 的 VertexBuffer,因此您所需要做的就是提取纹理,将其作为全局效果参数传递到着色器中,然后照常进行。

This is an old question, but I had to figure this out myself yesterday so I thought I'd post a followup:

If you're using the default FBX content processor and have the DefaultEffect property set to BasicEffect, you can get the Texture2D for the object via:

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

Note that the each mesh in the model may have a different texture.

The texture coordinates are stored in the MeshPart'sVertexBuffer along with position, etc. I've seen two vertex declarations. For a model/mesh that used a single texture (bitmap material in 3DS Max), the vertex declaration was VertexPositionNormalTexture.

For a model that had two textures (a bitmap and an opacity/alpha map), the declaration had the elements:

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

or, wrapped into an IVertexType structure,

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

and the equivelant HLSL structure:

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

Note that I changed .Position and .Normal from Vector4 and Vector3 to float4 and float3 before I posted this, and haven't tested it. It's possible that they may need to be changed back to Vector4 and float4.

Of course, you'll need a sampler and some basic logic in your pixel shader to read each texture. Assuming you've set two effect parameters xTexture0 and xTexture1 to Texture2D objects containing your color texture and opacity map,

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

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

and here's a simple two-texture pixel shader. If you only want one texture, just read from the first sampler and return the value, or apply lighting, 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;

} 

The relevant points here are that the texture coordinates are already present in the FBX and are already stored in each MeshPart's VertexBuffer, so all you need to do is extract the texture, pass it into your shader as a global effect parameter, and proceed as normal.

玩心态 2024-08-19 01:21:16

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

要回答你的第二个问题,你可以以一种迂回的方式解决它。由于模型默认使用 basiceffect 加载到内容管道中,因此纹理将被导入并分配给管道内部的着色器参数。因此,如果您想访问它,您必须查看模型网格部件的默认效果属性。 这里是描述此过程的论坛帖子。

更正确的答案是在完全自定义导入器和仅使用默认导入器之间进行折衷。您可以创建一个继承现有模型处理器的自定义模型处理器。在那里,您可以导入自己的自定义效果,以及自定义纹理和需要设置的任何参数。并将其设置在模型内容上。有一篇文章(Shawn Hargreave 的博客或 msdn 上)展示了如何执行此操作,但遗憾的是我目前找不到它。

祝你好运!

The reason it's not working is because you have to set the effect's parameters manually instead of relying on the basiceffect (which would have had the shader parameters set in the content pipeline). Now, I'm not familiar with your shader so I couldn't prescribe code to solve your problem ...

To answer your second question, you can get around it in a roundabout sort of way. Because the model loads in the content pipeline with basiceffect by default, the texture is imported and assigned to the shader's parameters inside of the pipeline. So if you want to access it you'd have to look at the modelmeshpart's default effect property. Here is a forum post that describes this process.

The more correct answer would be a compromise between a full on custom importer and just using the default. You can make a custom modelprocessor that inherits from the existing one. In there, you can import your own custom effect, along with your custom textures and whatever parameters you need to set. and set it on the modelcontent. There was an article (either on Shawn Hargreave's blog, or on msdn) that showed how to do this, but I'm failing to find it at the moment unfortunately.

good luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文