Exemple #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);
      }
    }
Exemple #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);
    }
Exemple #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 }
        }
      };
    }
Exemple #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;
    }