HLSL着色器,如何用它的原始颜色绘制模型?

时间:2011-02-16 21:25:45

标签: c# 3d xna hlsl sketchup

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

我编写了这个HLSL代码试图用它的原始颜色渲染这个模型,但是它不起作用,我在调用ModelMesh.Draw()方法时得到"The current vertex declaration does not include all the elements required by the current vertex shader. Color0 is missing"。这是我的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,到目前为止我能够做到的一切是在整个模型中使用着色器中定义的另一种颜色绘制模型:[

1 个答案:

答案 0 :(得分: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,右键单击,添加新项目&gt;内容管道扩展库
  2. 在该新项目中,添加一个新的内容处理器项目,类似于下面的内容。
  3. 重新编译,然后在内容项目中的模型.X文件条目的内容处理器字段中,选择新的导入程序(按照您在DisplayName属性中提供的名称)
  4. 这样做基本上是在将.X数据导入XNAs文档对象模型后拦截它的数据,在将其处理成新的Model类之前,处理器会检查是否存在顶点颜色通道,如果找不到,则在ModelProcessor创建VertexDeclaration并将所有顶点数据打包到要由GPU加载的VertexBuffer之前生成并添加它。

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

    [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它退出时的窗口 - 当你忘记评论它时,这不是一个真正令人讨厌的问题;)