Exemplo n.º 1
0
        private void ProcessEffect(DREffectBindingContent binding, ContentProcessorContext context)
        {
            if (binding.EffectType == DREffectType.CustomEffect)
            {
                if (!string.IsNullOrEmpty(binding.EffectAsset))
                {
                    // The effect is a prebuilt asset.
                    return;
                }

                // Build effect.
                if (binding.Effect == null)
                {
                    string message = string.Format(CultureInfo.InvariantCulture, "Material \"{0}\" does not have an effect.", binding.Name);
                    throw new InvalidContentException(message, binding.Identity);
                }

                if (String.IsNullOrEmpty(binding.Effect.Filename))
                {
                    string message = string.Format(CultureInfo.InvariantCulture, "Material \"{0}\" does not have a valid effect file. File name is null or empty.", binding.Name);
                    throw new InvalidContentException(message, binding.Identity);
                }

                binding.CompiledEffect = OnBuildEffect(binding.Effect, context);
            }
        }
Exemplo n.º 2
0
        private void ProcessTextures(DREffectBindingContent material, ContentProcessorContext context, ContentIdentity identity)
        {
            // We have to call OnBuildTexture (which calls BuildAsset) to replace the
            // current texture references (.jpg, .bmp, etc.) with references to the built
            // textures (.xnb).

            // For stock effects we remove all unnecessary textures.
            if (material.EffectType == DREffectType.AlphaTestEffect ||
                material.EffectType == DREffectType.BasicEffect ||
                material.EffectType == DREffectType.SkinnedEffect)
            {
                var texture = material.Texture;
                material.Textures.Clear();

                if (texture != null)
                {
                    material.Texture = BuildTexture("Texture", texture, context, identity);
                }

                return;
            }

            if (material.EffectType == DREffectType.DualTextureEffect)
            {
                var texture  = material.Texture;
                var texture2 = material.Texture2;
                material.Textures.Clear();

                if (texture != null)
                {
                    material.Texture = BuildTexture(DualTextureMaterialContent.TextureKey, texture, context, identity);
                }
                if (texture2 != null)
                {
                    material.Texture2 = BuildTexture(DualTextureMaterialContent.Texture2Key, texture2, context, identity);
                }

                return;
            }

            if (material.EffectType == DREffectType.EnvironmentMapEffect)
            {
                var texture        = material.Texture;
                var environmentMap = material.EnvironmentMap;
                material.Textures.Clear();

                if (texture != null)
                {
                    material.Texture = BuildTexture(EnvironmentMapMaterialContent.TextureKey, texture, context, identity);
                }
                if (environmentMap != null)
                {
                    material.EnvironmentMap = BuildTexture(EnvironmentMapMaterialContent.EnvironmentMapKey, environmentMap, context, identity);
                }

                return;
            }

            // Custom effect: Build all textures stored in the MaterialContent.
            foreach (var entry in material.Textures.ToArray())
            {
                material.Textures[entry.Key] = BuildTexture(entry.Key, entry.Value, context, identity);
            }
        }
Exemplo n.º 3
0
        private DRMaterialContent ProcessInternal(MaterialContent input, ContentProcessorContext context)
        {
            // Create effect binding for default render pass.
            var binding = new DREffectBindingContent
            {
                Name     = DefaultPass,
                Identity = input.Identity
            };

            // Copy opaque data from material content.
            ValidateOpaqueData(input);

            foreach (var entry in input.OpaqueData)
            {
                binding.OpaqueData.Add(entry.Key, entry.Value);
            }

            foreach (var entry in input.Textures)
            {
                binding.Textures.Add(entry.Key, entry.Value);
            }

            // ----- Effect
            if (input is AlphaTestMaterialContent)
            {
                binding.EffectType = DREffectType.AlphaTestEffect;
            }
            else if (input is DualTextureMaterialContent)
            {
                binding.EffectType = DREffectType.DualTextureEffect;
            }
            else if (input is EnvironmentMapMaterialContent)
            {
                binding.EffectType = DREffectType.EnvironmentMapEffect;
            }
            else if (input is SkinnedMaterialContent)
            {
                binding.EffectType = DREffectType.SkinnedEffect;
            }
            else
            {
                var effectMaterial = input as EffectMaterialContent;
                if (effectMaterial == null || effectMaterial.Effect == null || string.IsNullOrEmpty(effectMaterial.Effect.Filename))
                {
                    // The material is either
                    //  - a BasicMaterialContent (default)
                    //  - or an EffectMaterialContent without an effect.
                    // --> Use the DefaultEffect.
                    binding.EffectType = DefaultEffectType;

                    if (DefaultEffectType == DREffectType.CustomEffect)
                    {
                        if (String.IsNullOrEmpty(DefaultEffectFile))
                        {
                            throw new InvalidContentException("DefaultEffectType is set to CustomEffect, but DefaultEffectFile is null or empty.", input.Identity);
                        }

                        string fileName = ContentHelper.FindFile(DefaultEffectFile, input.Identity);
                        binding.Effect = new ExternalReference <EffectContent>(fileName);
                    }
                }
            }

            ProcessEffect(binding, context);

            // ----- Textures
            foreach (var texture in binding.Textures.Values)
            {
                // Store texture parameters in opaque data.
                texture.OpaqueData.Clear();
                texture.OpaqueData.Add("ColorKeyColor", ColorKeyColor);
                texture.OpaqueData.Add("ColorKeyEnabled", ColorKeyEnabled);
                texture.OpaqueData.Add("GenerateMipmaps", GenerateMipmaps);
                texture.OpaqueData.Add("InputGamma", InputTextureGamma);
                texture.OpaqueData.Add("OutputGamma", OutputTextureGamma);
                texture.OpaqueData.Add("PremultiplyAlpha", PremultiplyTextureAlpha);
                texture.OpaqueData.Add("ResizeToPowerOfTwo", ResizeTexturesToPowerOfTwo);
                texture.OpaqueData.Add("Format", TextureFormat);
                texture.OpaqueData.Add("ReferenceAlpha", ReferenceAlpha);
                texture.OpaqueData.Add("ScaleAlphaToCoverage", ScaleTextureAlphaToCoverage);
            }

            ProcessTextures(binding, context, input.Identity);

            // Create DigitalRune material with default render pass.
            return(new DRMaterialContent
            {
                Name = input.Name,
                Identity = input.Identity,
                Passes = new Dictionary <string, DREffectBindingContent>
                {
                    { DefaultPass, binding }
                }
            });
        }
Exemplo n.º 4
0
        private DRMaterialContent ProcessInternal(DRMaterialContent material, ContentProcessorContext context)
        {
            material.Passes = new Dictionary <string, DREffectBindingContent>();

            // Parse XML file.
            var document = material.Definition;
            var identity = material.Identity;

            var materialElement = document.Root;

            if (materialElement == null || materialElement.Name != "Material")
            {
                string message = string.Format(CultureInfo.InvariantCulture, "Root element \"<Material>\" is missing in XML.");
                throw new InvalidContentException(message, identity);
            }

            // Override material name, if attribute is set.
            material.Name = (string)materialElement.Attribute("Name") ?? material.Name;

            // Create effect bindings for all render passes.
            foreach (var passElement in materialElement.Elements("Pass"))
            {
                string pass = passElement.GetMandatoryAttribute("Name", identity);
                if (material.Passes.ContainsKey(pass))
                {
                    string message = XmlHelper.GetExceptionMessage(passElement, "Duplicate entry. The pass \"{0}\" was already defined.", pass);
                    throw new InvalidContentException(message, identity);
                }

                var binding = new DREffectBindingContent {
                    Name = pass, Identity = identity
                };

                // Skip this pass if the graphics profile does not match the actual target profile.
                string profile      = (string)passElement.Attribute("Profile") ?? "ANY";
                string profileLower = profile.ToUpperInvariant();
                if (profileLower == "REACH")
                {
                    if (context.TargetProfile != GraphicsProfile.Reach)
                    {
                        continue;
                    }
                }
                else if (profileLower == "HIDEF")
                {
                    if (context.TargetProfile != GraphicsProfile.HiDef)
                    {
                        continue;
                    }
                }
                else if (profileLower != "ANY")
                {
                    string message = XmlHelper.GetExceptionMessage(passElement, "Unknown profile: \"{0}\". Allowed values are \"Reach\", \"HiDef\" or \"Any\"", profile);
                    throw new InvalidContentException(message, identity);
                }

                // ----- Effect
                string effectName = passElement.GetMandatoryAttribute("Effect", identity);
                switch (effectName)
                {
                case "AlphaTestEffect":
                    binding.EffectType = DREffectType.AlphaTestEffect;
                    break;

                case "BasicEffect":
                    binding.EffectType = DREffectType.BasicEffect;
                    break;

                case "DualTextureEffect":
                    binding.EffectType = DREffectType.DualTextureEffect;
                    break;

                case "EnvironmentMapEffect":
                    binding.EffectType = DREffectType.EnvironmentMapEffect;
                    break;

                case "SkinnedEffect":
                    binding.EffectType = DREffectType.SkinnedEffect;
                    break;

                default:
                    binding.EffectType = DREffectType.CustomEffect;
                    if (string.IsNullOrEmpty(Path.GetExtension(effectName)))
                    {
                        // The effect is a prebuilt asset. effectName is the name of the asset,
                        // for example: effectName = "DigitalRune\GBuffer".
                        binding.EffectAsset = effectName;
                    }
                    else
                    {
                        // The effect is a local .fx file.
                        effectName     = ContentHelper.FindFile(effectName, identity);
                        binding.Effect = new ExternalReference <EffectContent>(effectName);
                    }
                    break;
                }

                ProcessEffect(binding, context);

                // ----- Parameters
                foreach (var parameterElement in passElement.Elements("Parameter"))
                {
                    string name = parameterElement.GetMandatoryAttribute("Name", identity);
                    if (binding.OpaqueData.ContainsKey(name))
                    {
                        string message = XmlHelper.GetExceptionMessage(parameterElement, "Duplicate entry. The parameter \"{0}\" was already defined.", name);
                        throw new InvalidContentException(message, identity);
                    }

                    object value = parameterElement.Attribute("Value").ToParameterValue(null, identity);
                    if (value != null)
                    {
                        binding.OpaqueData.Add(name, value);
                    }
                }

                // ----- Textures
                foreach (var textureElement in passElement.Elements("Texture"))
                {
                    string name = textureElement.GetMandatoryAttribute("Name", identity);
                    if (binding.Textures.ContainsKey(name))
                    {
                        string message = XmlHelper.GetExceptionMessage(textureElement, "Duplicate entry. The texture \"{0}\" was already defined.", name);
                        throw new InvalidContentException(message, identity);
                    }

                    string fileName = textureElement.GetMandatoryAttribute("File", identity);
                    fileName = ContentHelper.FindFile(fileName, identity);

                    // Texture processor parameters.
                    var             colorKeyAttribute    = textureElement.Attribute("ColorKey");
                    bool            colorKeyEnabled      = colorKeyAttribute != null;
                    Color           colorKeyColor        = colorKeyAttribute.ToColor(Color.Magenta, identity);
                    bool            generateMipmaps      = (bool?)textureElement.Attribute("GenerateMipmaps") ?? true;
                    float           inputGamma           = (float?)textureElement.Attribute("InputGamma") ?? 2.2f;
                    float           outputGamma          = (float?)textureElement.Attribute("OutputGamma") ?? 2.2f;
                    bool            premultiplyAlpha     = (bool?)textureElement.Attribute("PremultiplyAlpha") ?? true;
                    bool            resizeToPowerOfTwo   = (bool?)textureElement.Attribute("ResizeToPowerOfTwo") ?? false;
                    DRTextureFormat textureFormat        = textureElement.Attribute("Format").ToTextureFormat(DRTextureFormat.Dxt, identity);
                    float           referenceAlpha       = (float?)textureElement.Attribute("ReferenceAlpha") ?? 0.9f;
                    bool            scaleAlphaToCoverage = (bool?)textureElement.Attribute("ScaleAlphaToCoverage") ?? false;

                    // Store texture parameters in opaque data.
                    var texture = new ExternalReference <TextureContent>(fileName);
                    var defaultTextureProcessor = new DRTextureProcessor();
                    if (colorKeyColor != defaultTextureProcessor.ColorKeyColor)
                    {
                        texture.OpaqueData.Add("ColorKeyColor", colorKeyColor);
                    }
                    if (colorKeyEnabled != defaultTextureProcessor.ColorKeyEnabled)
                    {
                        texture.OpaqueData.Add("ColorKeyEnabled", colorKeyEnabled);
                    }
                    if (generateMipmaps != defaultTextureProcessor.GenerateMipmaps)
                    {
                        texture.OpaqueData.Add("GenerateMipmaps", generateMipmaps);
                    }
                    if (inputGamma != defaultTextureProcessor.InputGamma)
                    {
                        texture.OpaqueData.Add("InputGamma", inputGamma);
                    }
                    if (outputGamma != defaultTextureProcessor.OutputGamma)
                    {
                        texture.OpaqueData.Add("OutputGamma", outputGamma);
                    }
                    if (premultiplyAlpha != defaultTextureProcessor.PremultiplyAlpha)
                    {
                        texture.OpaqueData.Add("PremultiplyAlpha", premultiplyAlpha);
                    }
                    if (resizeToPowerOfTwo != defaultTextureProcessor.ResizeToPowerOfTwo)
                    {
                        texture.OpaqueData.Add("ResizeToPowerOfTwo", resizeToPowerOfTwo);
                    }
                    if (textureFormat != defaultTextureProcessor.Format)
                    {
                        texture.OpaqueData.Add("Format", textureFormat);
                    }
                    if (referenceAlpha != defaultTextureProcessor.ReferenceAlpha)
                    {
                        texture.OpaqueData.Add("ReferenceAlpha", referenceAlpha);
                    }
                    if (scaleAlphaToCoverage != defaultTextureProcessor.ScaleAlphaToCoverage)
                    {
                        texture.OpaqueData.Add("ScaleAlphaToCoverage", scaleAlphaToCoverage);
                    }

                    binding.Textures.Add(name, texture);
                }

                ProcessTextures(binding, context, identity);

                material.Passes.Add(pass, binding);
            }

            return(material);
        }