1

我用 Google SketchUp 制作了这个非常简单的 3D 模型,导出为 .x 格式,模型是一个简单的立方体,没有纹理,每个面只有不同的颜色。

我已经编写了这个 HLSL 代码来尝试用它的原始颜色渲染这个模型,但是它不起作用,我"The current vertex declaration does not include all the elements required by the current vertex shader. Color0 is missing"在调用 ModelMesh.Draw() 方法时得到一个。这是我的 HLSL 代码:

float4x4 World;
float4x4 View;
float4x4 Projection;

struct AppToVertex
{
    float4 Position : POSITION0;
    float4 Color    : COLOR0;
};

struct VertexToPixel
{
    float4 Position : POSITION0;
    float4 Color    : COLOR0;
};

VertexToPixel ColoredVS(AppToVertex input)
{
    VertexToPixel output = (VertexToPixel)0;

    float4 iTransformed = mul(input.Position, World);
    float4 iView = mul(iTransformed, View);
    float4 iProjection = mul(iView, Projection);

    output.Position = iProjection;
    output.Color = input.Color;

    return output;
}

float4 ColoredPS(VertexToPixel input) : COLOR
{
    return input.Color;
}

technique Colored
{
    pass Pass0
    {
        VertexShader = compile vs_2_0 ColoredVS();
        PixelShader = compile ps_2_0 ColoredPS();
    }
}

这可能是一个菜鸟问题,我知道我可以通过简单地使用 BasicEffect 类(有效)来绘制这个模型,但我这样做只是为了学习 HLSL,到目前为止我所能做的就是绘制在整个模型的着色器中定义了另一种颜色的模型:[

4

1 回答 1

2

这是我第一次查看 .X,但我不相信 Sketchup 正在为您的模型导出顶点颜色。

(对这种格式有更多经验的人,如果您发现任何错误,请纠正我!)

template Mesh {
<3D82AB44-62DA-11cf-AB39-0020AF71E433>
DWORD nVertices;
array Vector vertices[nVertices];
DWORD nFaces;
array MeshFace faces[nFaces];
[...]
}

template MeshVertexColors {
<1630B821-7842-11cf-8F52-0040333594A3>
DWORD nVertexColors;
array IndexedColor vertexColors[nVertexColors];
}

查看模型的 .X“声明”,我可以看到网格的几何形状、颜色和法线等通道存储为单独的“对象”(就像它们在 XNAs 内容管道中的 DOM 中一样)。

虽然您的模型定义了位置数据 (Mesh)、法线数据 (MeshNormals) 和纹理坐标 (MeshTextureCoords)(均在模板部分下方定义),但我看不到 MeshVertexColors 类型的部分。

相反,似乎定义了四种材质,并使用

 template MeshMaterialList {
<F6F23F42-7686-11cf-8F52-0040333594A3>
DWORD nMaterials;
DWORD nFaceIndexes;
array DWORD faceIndexes[nFaceIndexes];
[Material]
}

部分。

因此,您没有要导入的 ModelProcessor 或要显示的着色器的任何顶点颜色。

Sketchup 中可能有一个选项可以启用顶点颜色。但是,如果您找不到/不想查找它,您可以通过在内容管道扩展项目中创建内容处理器来添加和删除内容管道中的顶点通道。

(我知道这听起来很不愉快,但实际上,当你习惯它时,这是一个非常棒的功能!)

网上有很多关于这个的教程,但简而言之:

  1. 进入VS,右键,添加新项目>内容管道扩展库
  2. 在那个新项目中,添加一个新的内容处理器项目,如下所示。
  3. 重新编译,然后在 Content 项目中模型 .X 文件条目的 Content Processor 字段中,选择新的导入器(按您在 DisplayName 属性中提供的名称)

这实际上是在将 .X 数据导入 XNA 文档对象模型之后,在将其处理为新的模型类之前,从您的 .X 中截取数据,处理器检查是否存在顶点颜色通道,如果有未找到,生成并添加它,然后 ModelProcessor 创建 VertexDeclaration 并将所有顶点数据打包到 VertexBuffer 中以供 GPU 加载。

这只会将立方体显示为纯紫色,但至少您可以看到着色器是否正常工作。

[ContentProcessor(DisplayName = "Processor to make sure we have vertex colours in all models")]
public class Character_Model_Processor : ModelProcessor
{
    public override ModelContent Process(NodeContent input, ContentProcessorContext context)
    {
        foreach(NodeContent c in input.Children)
        {
            if(c is MeshContent)
            {
                foreach(GeometryContent g in (c as MeshContent).Geometry)
                {
                    //Stop here and check out the VertexContent object (g.Vertices) and the Channels member of it to see how
                    //vertex data is stored in the DOM, and what you can do with it.
                    System.Diagnostics.Debugger.Launch();

                    AddVertexColorChannel(g.Vertices);
                }
            }
        }

        ModelContent model = base.Process(input, context);

        return model;
    }

    private void AddVertexColorChannel(VertexContent content)
    {
        if(content.Channels.Contains(VertexChannelNames.Color(0)) == false)
        {
            List<Microsoft.Xna.Framework.Color> VertexColors = new List<Microsoft.Xna.Framework.Color>();

            for (int i = 0; i < content.VertexCount; i++)
            {
                VertexColors.Add(Color.Purple);
            }

            content.Channels.Add(VertexChannelNames.Color(0), VertexColors);
        }
    }
}

祝你好运,很抱歉,如果你已经知道了大部分内容,我想如果你正在编写自己的着色器但更安全,我想你可能知道所有关于管道修改的知识:)

编辑:只是关于 System.Diag... 行的注释,如果您闯入调试器,请确保您在完成探索时按 F5 并让它运行,否则它会占用您的主 VS 窗口当它退出时 - 当您忘记将其注释掉时,这不是一个问题,只是真的很烦人;)

于 2011-02-16T22:37:59.523 回答