public static MaterialShaderResult Generate(MaterialDescriptor materialDescriptor, MaterialGeneratorContext context, string rootMaterialFriendlyName) { if (materialDescriptor == null) { throw new ArgumentNullException("materialDescriptor"); } if (context == null) { throw new ArgumentNullException("context"); } var result = new MaterialShaderResult(); context.Log = result; result.Material = context.Material; context.PushMaterial(materialDescriptor, rootMaterialFriendlyName); context.Step = MaterialGeneratorStep.PassesEvaluation; materialDescriptor.Visit(context); context.Step = MaterialGeneratorStep.GenerateShader; for (int pass = 0; pass < context.PassCount; ++pass) { // TODO: It would be better if the passes would get executed like this: // [object0 pass0][object0 pass1] [object1 pass0][object1 pass1] // Instead of like this: // [object0 pass0][object1 pass0] [object0 pass1][object1 pass1] // // Caveat: While the first method improves the depth sorting (for transparents), it also causes more state changes. var materialPass = context.PushPass(); context.PushLayer(null); materialDescriptor.Visit(context); context.PopLayer(); ShaderSource CustomShader = context.ComputeCustomShaderSource(); if (CustomShader != null) { materialPass.Parameters.Set(MaterialKeys.CustomShaders, CustomShader); } else { materialPass.Parameters.Set(MaterialKeys.VertexStageSurfaceShaders, context.ComputeShaderSource(MaterialShaderStage.Vertex)); materialPass.Parameters.Set(MaterialKeys.DomainStageSurfaceShaders, context.ComputeShaderSource(MaterialShaderStage.Domain)); materialPass.Parameters.Set(MaterialKeys.PixelStageSurfaceShaders, context.ComputeShaderSource(MaterialShaderStage.Pixel)); materialPass.Parameters.Set(MaterialKeys.VertexStageStreamInitializer, context.GenerateStreamInitializers(MaterialShaderStage.Vertex)); materialPass.Parameters.Set(MaterialKeys.DomainStageStreamInitializer, context.GenerateStreamInitializers(MaterialShaderStage.Domain)); materialPass.Parameters.Set(MaterialKeys.PixelStageStreamInitializer, context.GenerateStreamInitializers(MaterialShaderStage.Pixel)); } context.PopPass(); } context.PopMaterial(); return(result); }
public virtual void Visit(MaterialGeneratorContext context) { // If not enabled, or Material or BlendMap are null, skip this layer if (!Enabled || Material is null || BlendMap is null || context.FindAsset is null) { return; } // Find the material from the reference var material = Material.Descriptor ?? context.FindAsset(Material) as IMaterialDescriptor; if (material is null) { context.Log.Error($"Unable to find material [{Material}]."); return; } // Check that material is valid var materialName = context.GetAssetFriendlyName(Material); if (!context.PushMaterial(material, materialName)) { return; } try { // TODO: Because we are not fully supporting Streams declaration in shaders, we have to workaround this limitation by using a dynamic shader (inline) // Push a layer for the sub-material context.PushOverrides(Overrides); context.PushLayer(BlendMap); // Generate the material shaders into the current context material.Visit(context); } finally { // Pop the stack context.PopLayer(); context.PopOverrides(); context.PopMaterial(); } }