2
\$\begingroup\$

I have tried creating a simple content processor that assigns the custom effect I created to models instead of the default BasicEffect.

[ContentProcessor(DisplayName = "Shadow Mapping Model")]
public class ShadowMappingModelProcessor : ModelProcessor
{
    protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)
    {
        EffectMaterialContent shadowMappingMaterial = new EffectMaterialContent();
        shadowMappingMaterial.Effect = new ExternalReference<EffectContent>("Effects/MultipassShadowMapping.fx");
        return context.Convert<MaterialContent, MaterialContent>(shadowMappingMaterial, typeof(MaterialProcessor).Name);
    }
}

This works, but when I go to draw a model in a game, the effect has no material properties assigned. How would I go about assigning, say, my DiffuseColor or SpecularColor shader parameter to white or (better) can I assign it to some value specified by the artist in the model? (I think this may have something to do with the OpaqueDataDictionary but I am confused on how to use it--the content pipeline has always been a black box to me.)

\$\endgroup\$
3
  • \$\begingroup\$ If I remember correctly, all you need to do is set OpaqueData like .Add("DiffuseColor", new Vector4(1,0,0,1)) and it will be then assigned to global variable DiffuseColor in your shader. And this is actually exported from .fbx files - this is how you get a texture. So you can write it directly to them (but that format is a little complex) \$\endgroup\$
    – Kikaimaru
    Oct 26, 2012 at 9:48
  • \$\begingroup\$ Thanks that seems to work if I want to hard code values (or I could use a property on the processor to set a chosen value). Do .fbx files contain artist specified data like SpecularPower and is that accessible to me in the content processor somewhere already (read by the default importer maybe...)? \$\endgroup\$
    – Nick
    Oct 26, 2012 at 10:11
  • \$\begingroup\$ Well personaly I do it this way: I have file .model (its xml imported by xna content pipeline and processed to my ModelContent class) that points to .fbx and to .material file (another xml), and material file points to .fx and has list of properties and values that i want to set to that material. I think its possible to have these values in .fbx but i dont know exaclty how. But they are easily found in .x files.d d \$\endgroup\$
    – Kikaimaru
    Oct 26, 2012 at 10:23

1 Answer 1

2
\$\begingroup\$

Kikaimaru gave me some helpful tips, so here is an answer (a code example) to my own question based on what I've learned about custom shaders and building materials in the content pipeline:

[ContentProcessor(DisplayName = "Shadow Mapping Model")]
public class ShadowMappingModelProcessor : ModelProcessor
{
    protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)
    {
        // We want to use a custom shader we wrote ourselves, so we build our .fx file, putting shader parameter 
        // values into opaque data and textures using our shader variable names as the keys.

        // You can see these default "key (value)" entries on "material" by using the content pipeline debug project here:
        // (http://badcorporatelogo.wordpress.com/2010/10/31/xna-content-pipeline-debugging-4-0/)

        // default "material" opaque data:
        // ===============================
        // DiffuseColor (vector3)
        // EmissiveColor (vector3)
        // SpecularColor (vector3)
        // Alpha (float)
        // SpecularPower (float)
        // VertexColorEnabled (bool)
        //
        // default "material" textures:
        // ============================
        // Texture (external texture reference)

        // use our custom effect
        EffectMaterialContent shadowMappingMaterial = new EffectMaterialContent();
        shadowMappingMaterial.Effect = new ExternalReference<EffectContent>("Effects/MultipassShadowMapping.fx");

        // transfer opaque data
        shadowMappingMaterial.OpaqueData.Add("DiffuseColor", new Vector4((Vector3)material.OpaqueData["DiffuseColor"], (float)material.OpaqueData["Alpha"]));
        shadowMappingMaterial.OpaqueData.Add("SpecularColor", material.OpaqueData["SpecularColor"]);
        shadowMappingMaterial.OpaqueData.Add("SpecularPower", material.OpaqueData["SpecularPower"]);

        // transfer texture
        if (material.Textures.ContainsKey("Texture"))
        {
            shadowMappingMaterial.OpaqueData.Add("DiffuseTextureEnabled", true);
            shadowMappingMaterial.Textures.Add("DiffuseTexture", material.Textures["Texture"]);
        }

        return context.Convert<MaterialContent, MaterialContent>(shadowMappingMaterial, typeof(MaterialProcessor).Name);
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .