Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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.)

share|improve this question
    
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) –  Kikaimaru Oct 26 '12 at 9:48
    
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...)? –  Nick Oct 26 '12 at 10:11
    
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 –  Kikaimaru Oct 26 '12 at 10:23
add comment

1 Answer

up vote 2 down vote accepted

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);
    }
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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