使用自定义效果时缺少网格颜色,但使用 BasicEffect 时没有

Posted

技术标签:

【中文标题】使用自定义效果时缺少网格颜色,但使用 BasicEffect 时没有【英文标题】:Mesh color is missing when using a custom effect, but not when using a BasicEffect 【发布时间】:2013-08-17 21:14:22 【问题描述】:

这可能是一些新手问题,但我正在尝试用颜色(材料)渲染一个 fbx 模型。

问题是,当我尝试使用 BasicEffect 时,一切顺利,颜色渲染得很好 - 但现在我正在编写一个自定义 HLSL 效果文件,每当我尝试用它渲染模型时,它表示模型没有颜色:

当前顶点声明不包括所有元素 当前顶点着色器需要。缺少 Color0。

这可能是一些愚蠢的语义错误(或类似的错误),因为我对使用 HLSL 不是很有经验。 无论如何,这是代码(最初取自 Riemers 教程):

float4x4 xWorldViewProjection;

float4x4 xWorld;
float3 xLightPos;
float xLightPower;
float xAmbient;

struct VertexToPixel

    float4 Position     : POSITION;    
    float3 Normal        : TEXCOORD0;
    float3 Position3D    : TEXCOORD1;
    float4 Color        : COLOR0;
;

struct PixelToFrame

    float4 Color        : COLOR0;
;

float DotProduct(float3 lightPos, float3 pos3D, float3 normal)

    float3 lightDir = normalize(pos3D - lightPos);
        return dot(-lightDir, normal);    


VertexToPixel SimplestVertexShader( float4 inPos : POSITION0, float3 inNormal: NORMAL0, float4 inColor : COLOR0)

    VertexToPixel Output = (VertexToPixel)0;

    Output.Position =mul(inPos, xWorldViewProjection);
    Output.Normal = normalize(mul(inNormal, (float3x3)xWorld));    
    Output.Position3D = mul(inPos, xWorld);
    Output.Color = inColor;

    return Output;


PixelToFrame OurFirstPixelShader(VertexToPixel PSIn)

    PixelToFrame Output = (PixelToFrame)0;    

    float diffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal);
    diffuseLightingFactor = saturate(diffuseLightingFactor);
    diffuseLightingFactor *= xLightPower;

    Output.Color = PSIn.Color* (diffuseLightingFactor + xAmbient);

    return Output;


technique Simplest

    pass Pass0
    
        VertexShader = compile vs_3_0 SimplestVertexShader();
        PixelShader = compile ps_3_0 OurFirstPixelShader();
    

以及使用的 XNA 代码:

(加载后:)

    foreach (ModelMesh mesh in MainRoom.Meshes)
        foreach (ModelMeshPart meshPart in mesh.MeshParts)
            meshPart.Effect = roomEffect.Clone();

...

private void DrawModel(Model model, Matrix world)

    Matrix[] bones = new Matrix[model.Bones.Count];
    model.CopyAbsoluteBoneTransformsTo(bones);


    foreach (ModelMesh mesh in model.Meshes)
    
        foreach (Effect currentEffect in mesh.Effects)
        
            Matrix worldMatrix = bones[mesh.ParentBone.Index] * world;

            roomEffect.CurrentTechnique = roomEffect.Techniques["Simplest"];
            currentEffect.Parameters["xWorldViewProjection"].SetValue(worldMatrix * camera.view * camera.projection);
            currentEffect.Parameters["xWorld"].SetValue(worldMatrix);
            currentEffect.Parameters["xLightPos"].SetValue(lightPos);
            currentEffect.Parameters["xLightPower"].SetValue(lightPower);
            currentEffect.Parameters["xAmbient"].SetValue(ambientPower);
        
        mesh.Draw();
    

【问题讨论】:

快速浏览表明这不是您的 HLSL 的问题,而是您的网格未指定颜色数据。如果您将BasicEffectVertexColorEnabled = true 一起使用,您会得到同样的错误吗?这将启用使用COLOR0 的基本效果着色器版本。因此,请尝试验证这是否是您的模型有问题。 @AndrewRussell 是的,就是这样。启用 VertexColor 确实会导致相同的错误。这虽然提出了一个不同的问题,因为使用没有 VertexColor 的 BasicEffect 会渲染原始颜色,我怎么能这样做呢? (我想我应该使用其他东西而不是 Color0) 【参考方案1】:

很高兴,在阅读了@AndrewRussell 的评论和@Cole Campbell 's answer 之后,我终于设法解决了问题(以及我的代码中的一些其他错误)。

最终(工作)代码现在是:

float4x4 xWorldViewProjection;

float4x4 xWorld;
float3 xLightPos;
float xLightPower;
float xAmbient;
float3 DiffuseColor;

struct VertexToPixel

    float4 Position      : POSITION;    
    float3 Normal        : TEXCOORD0;
    float3 Position3d    : TEXCOORD1;

;

struct PixelToFrame

    float4 Color        : COLOR0;
;

float DotProduct(float3 lightPos, float3 pos3D, float3 normal)

    float3 lightDir = normalize(pos3D - lightPos);
        return dot(-lightDir, normal);    


VertexToPixel SimplestVertexShader(float4 inPosition : POSITION, float3 inNormal : TEXCOORD0)

    VertexToPixel Output = (VertexToPixel)0;

    Output.Position = mul(inPosition, xWorldViewProjection);
    Output.Normal = normalize(mul(inNormal, (float3x3)xWorld));    
    Output.Position3d = mul(inPosition, xWorld);

    return Output;


PixelToFrame OurFirstPixelShader(VertexToPixel PSIn)

    PixelToFrame Output = (PixelToFrame)0;    

    float diffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3d, PSIn.Normal);
    diffuseLightingFactor = saturate(diffuseLightingFactor);
    diffuseLightingFactor *= xLightPower;

    Output.Color = float4(DiffuseColor, 1) * (diffuseLightingFactor + xAmbient);

    return Output;


technique Simplest

    pass Pass0
    
        VertexShader = compile vs_3_0 SimplestVertexShader();
        PixelShader = compile ps_3_0 OurFirstPixelShader();
    

...

List<Vector3> OriginalDiffuseColors = new List<Vector3>();

...

protected override void LoadContent()

    ...

    foreach (ModelMesh mesh in MainRoom.Meshes)
    
         foreach (BasicEffect effect in mesh.Effects)
             OriginalDiffuseColors.Add(effect.DiffuseColor);
         foreach (ModelMeshPart meshPart in mesh.MeshParts)
             meshPart.Effect = roomEffect.Clone();
    

...

private void DrawModel(Model model, Matrix world)

    Matrix[] bones = new Matrix[model.Bones.Count];
    model.CopyAbsoluteBoneTransformsTo(bones);

    roomEffect.CurrentTechnique = roomEffect.Techniques["Simplest"];

    int count = 0;
    foreach (ModelMesh mesh in model.Meshes)
    
        foreach (Effect currentEffect in mesh.Effects)
        
            Matrix worldMatrix = bones[mesh.ParentBone.Index] * world;
            currentEffect.Parameters["xWorldViewProjection"].SetValue(worldMatrix * camera.view * camera.projection);
            currentEffect.Parameters["xWorld"].SetValue(worldMatrix);
            currentEffect.Parameters["xLightPos"].SetValue(lightPos);
            currentEffect.Parameters["xLightPower"].SetValue(lightPower);
            currentEffect.Parameters["xAmbient"].SetValue(ambientPower);
            currentEffect.Parameters["DiffuseColor"].SetValue(OriginalDiffuseColors[count++]);
        
        mesh.Draw();
    

感谢所有帮助。 =]

【讨论】:

以上是关于使用自定义效果时缺少网格颜色,但使用 BasicEffect 时没有的主要内容,如果未能解决你的问题,请参考以下文章

如图,表格边框之外有灰色边框是怎么回事?

将自定义颜色添加到 w2ui 单元格 [网格]

Datagrid上的自定义标题颜色?

使用 Swift 3 Xcode 8 加载时缺少自定义 XIB

python使用matplotlib可视化自定义设置坐标轴的范围自定义设置主坐标轴刻度和次坐标轴刻度自定义坐标轴刻度的显示样式自定义坐标轴刻度数值的颜色以及小数点位数添加坐标轴刻度网格线

当 Datagrid 失去焦点时,WPF DataGridRow 自定义样式被解除