0
\$\begingroup\$

I am currently trying to code my own HLSL effect file, in order to render an FBX model I made with Autodesk maya, and to which I have applied some materials (colors).

before trying to write an effect file, I have tried using XNA's BasicEffect, which rendered the model as expected with the materials I had set in maya. Now though, when I'm using my own HLSL effect file, there's always an error saying that my model doesn't have any colors:

The current vertex declaration does not include all the elements required by the current vertex shader. Color0 is missing.

My HLSL effect file (partially leared from riemers.net):

float4x4 xWorldViewProjection;

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

struct VertexToPixel
{
    float4 Position     : POSITION;    
    float4 Color        : COLOR0;
    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(VertexToPixel input)
{
    VertexToPixel Output = (VertexToPixel)0;

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

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

And my XNA code:

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

I'm fairly new to HLSL (but not to XNA though), any help would be nice.

EDIT: I have also tried rendering a different model with materials, but it just gives the same error.





Solution: Thanks to Cole Campbell's answer and, the full working code can be found here

\$\endgroup\$
2
  • \$\begingroup\$ While importing can you access the original model's vertex elements? What does it say? \$\endgroup\$ Commented Aug 16, 2013 at 9:39
  • \$\begingroup\$ @AvengerDr what do you mean by that? And how can I do this? \$\endgroup\$ Commented Aug 16, 2013 at 10:30

1 Answer 1

1
\$\begingroup\$

You're getting this error because your HLSL effect requires a color channel on the vertex data:

struct VertexToPixel
{
    float4 Position     : POSITION;    
    float4 Color        : COLOR0;
    float3 Normal        : TEXCOORD0;
    float3 Position3D    : TEXCOORD1;
};

...but your models don't have that channel on their vertices. Which channels exist on a model is a function of how they're exported from the program that created them.

The built-in XNA BasicEffect is intelligent enough to choose a different technique depending on the vertex format of the model being rendered, which is why it doesn't run into this problem.

The specific problem which you face arises from a misunderstanding of what Color0 constitutes. Material colors are different from vertex colors. Material colors should be specified as a parameter in the shader. Vertex colors are part of the vertex data.

You'll need to add a parameter to your shader that represents the material color:

float4 DiffuseColor;

...and copy it from the effect that you're replacing:

myEffect.Parameters["DiffuseColor"].SetValue(oldBasicEffect.DiffuseColor);

...and then use that to produce the final color for your vertex, and remove the float4 Color: COLOR0 declaration from your vertex data entirely.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the answer and solution! I've posted the new code as an answer to my simillar question at StackOverflow \$\endgroup\$ Commented Aug 16, 2013 at 17:24

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.