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\$
  • \$\begingroup\$ While importing can you access the original model's vertex elements? What does it say? \$\endgroup\$ – TheWanderer Aug 16 '13 at 9:39
  • \$\begingroup\$ @AvengerDr what do you mean by that? And how can I do this? \$\endgroup\$ – noamg97 Aug 16 '13 at 10:30
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\$
  • \$\begingroup\$ Thanks for the answer and solution! I've posted the new code as an answer to my simillar question at StackOverflow \$\endgroup\$ – noamg97 Aug 16 '13 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.