コード例 #1
0
        /// <summary>
        /// Gets or sets the <see cref="Nine.Graphics.Materials.Material"/> with the specified usage.
        /// </summary>
        public Material GetMaterialByUsage(MaterialUsage usage)
        {
            if (usage == MaterialUsage.Default)
            {
                return(this);
            }

            Material resolved = null;
            Material existing = null;

            if (materialUsages != null)
            {
                materialUsages.TryGetValue(usage, out existing);
            }
            if (existing != (resolved = ResolveMaterial(usage, existing)))
            {
                if (materialUsages == null)
                {
                    materialUsages = new Dictionary <MaterialUsage, Material>();
                }
                materialUsages[usage] = resolved;
            }
            if (resolved != null)
            {
                resolved.texture       = texture;
                resolved.alpha         = alpha;
                resolved.isAdditive    = isAdditive;
                resolved.isTransparent = isTransparent;
                resolved.texture       = texture;
                resolved.TwoSided      = TwoSided;
            }
            return(resolved);
        }
コード例 #2
0
 protected internal override string GetShaderCode(MaterialUsage usage)
 {
     if (usage != MaterialUsage.Default)
         return null;
     return GetShaderCode("ShadowMap").Replace("{$SAMPLECOUNT}", (filterSize * filterSize).ToString())
                                      .Replace("{$FILTERTAPS}", CreateFilterTaps());
 }
コード例 #3
0
        protected internal override void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance)
        {
            var part = ((AlphaTestMaterialPart)existingInstance);

            part.ReferenceAlpha = ReferenceAlpha;
            part.alphaFunction  = alphaFunction;
        }
コード例 #4
0
        public static string Build(MaterialPaintGroup materialPaintGroup, MaterialUsage usage)
        {
            var builder        = new StringBuilder();
            var index          = materialPaintGroup.MaterialGroup.MaterialParts.OfType <MaterialPaintGroup>().ToList().IndexOf(materialPaintGroup);
            var builderContext = MaterialGroupBuilder.CreateMaterialGroupBuilderContext(materialPaintGroup.MaterialParts, usage, false);

            builder.AppendLine(MaterialGroupBuilder.GetShaderCodeBody(builderContext, "VSMain", "PSMain"));

            builderContext.PixelShaderOutputs.AddRange(builderContext.PixelShaderInputs.Where(psi => psi.Out));

            builder.Append("void PixelShader(");
            builder.Append(string.Join(", ", Enumerable.Range(0, 1).Select(i => string.Concat("float paintBlend", index))
                                       .Concat(builderContext.PixelShaderInputs.Select(psi => string.Concat(psi.Type, " ", psi.Name)))
                                       .Concat(builderContext.PixelShaderOutputs.Select(pso => string.Concat("inout ", pso.Type, " ", AppendWithCasingCorrection(pso.Name, "paint"))))));
            builder.AppendLine(")");
            builder.AppendLine("{");
            foreach (var psi in builderContext.PixelShaderInputs)
            {
                builder.AppendLine(string.Concat("    ", psi.Type, " _", psi.Name, " = ", psi.Name, ";"));
            }
            foreach (var pso in builderContext.PixelShaderOutputs.Where(pso => !pso.In))
            {
                builder.AppendLine(string.Concat("    ", pso.Type, " _", pso.Name, ";"));
            }
            builder.Append("    PSMain(");
            builder.Append(string.Join(", ", builderContext.PixelShaderInputs.Select(psi => psi.Out ? string.Concat("_", psi.Name)  : psi.Name)
                                       .Concat(builderContext.PixelShaderOutputs.Where(pso => !pso.In).Select(pso => string.Concat("_", pso.Name)))));
            builder.AppendLine(");");
            foreach (var pso in builderContext.PixelShaderOutputs)
            {
                builder.AppendLine(string.Concat("    ", AppendWithCasingCorrection(pso.Name, "paint"), " += _", pso.Name, " * paintBlend", index, ";"));
            }
            builder.AppendLine("}");
            return(builder.ToString());
        }
コード例 #5
0
ファイル: SkinnedMaterial.cs プロジェクト: Hengle/Engine-Nine
        protected override Material OnResolveMaterial(MaterialUsage usage, Material existingInstance)
        {
#if !WINDOWS_PHONE
            if (usage == MaterialUsage.Depth)
            {
                var result = (existingInstance as DepthMaterial) ?? new DepthMaterial(GraphicsDevice)
                {
                    SkinningEnabled = true
                };
                result.AlphaTestEnabled = (texture != null && IsTransparent);
                return(result);
            }

            if (usage == MaterialUsage.DepthAndNormal)
            {
                var result = (existingInstance as DepthAndNormalMaterial) ?? new DepthAndNormalMaterial(GraphicsDevice)
                {
                    SkinningEnabled = true
                };
                result.specularPower = specularPower;
                return(result);
            }
#endif
            return(null);
        }
コード例 #6
0
        /// <summary>
        /// Gets the material with the specified usage that is attached to this material.
        /// </summary>
        protected internal override void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance)
        {
            var result    = ((MaterialPaintGroup)existingInstance);
            var srcCount  = materialParts.Count;
            var destCount = result.materialParts.Count;

            if (srcCount > 0 && destCount > 0)
            {
                var src      = 0;
                var dest     = 0;
                var srcPart  = materialParts[0];
                var destPart = result.materialParts[0];
                var srcType  = srcPart.GetType();
                var destType = destPart.GetType();

                // Source material parts is a super set of destination material parts.
                while (dest < destCount)
                {
                    destPart = result.materialParts[dest++];
                    destType = destPart.GetType();

                    while (src < srcCount)
                    {
                        srcPart = materialParts[src++];
                        srcType = srcPart.GetType();
                        if (srcType == destType)
                        {
                            srcPart.OnResolveMaterialPart(usage, destPart);
                            break;
                        }
                    }
                }
            }
        }
コード例 #7
0
 protected internal override string GetShaderCode(MaterialUsage usage)
 {
     // Specular power will be output to the alpha channel of the normal texture.
     return((usage != MaterialUsage.Default || usage != MaterialUsage.DepthAndNormal) ?
            GetShaderCode("SpecularMap").Replace("{$S1}", specularColorEnabled ? "" : "//")
            .Replace("{$S2}", specularColorEnabled ? "//" : "")
            .Replace("{$ST}", specularMapEnabled ? "" : "//") : null);
 }
コード例 #8
0
        protected internal override void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance)
        {
            var part = (BeginPaintGroupMaterialPart)existingInstance;

            part.maskTexture0     = maskTexture0;
            part.maskTexture1     = maskTexture1;
            part.maskTextureScale = maskTextureScale;
        }
コード例 #9
0
 private static Effect BuildByUsage(MaterialGroup input, MaterialUsage materialUsage)
 {
     byte[] effectCode;
     byte[] key;
     if (BuildByUsage(input, materialUsage, out effectCode, out key))
     {
         return(new Effect(input.GraphicsDevice, effectCode));
     }
     return(null);
 }
コード例 #10
0
        protected internal override string GetShaderCode(MaterialUsage usage)
        {
            if (usage != MaterialUsage.Default)
            {
                return(null);
            }

            return(GetShaderCode("EmissiveMap").Replace("{$E1}", emissiveColorEnabled ? "" : "//")
                   .Replace("{$E2}", emissiveColorEnabled ? "//" : "")
                   .Replace("{$ET}", emissiveMapEnabled ? "" : "//"));
        }
コード例 #11
0
 protected internal override void GetDependentParts(MaterialUsage usage, IList <Type> result)
 {
     if (usage == MaterialUsage.Depth)
     {
         result.Add(typeof(DepthMaterialPart));
     }
     if (usage == MaterialUsage.DepthAndNormal)
     {
         result.Add(typeof(DepthAndNormalMaterialPart));
     }
 }
コード例 #12
0
        /// <summary>
        /// Puts the dependent parts into the result list.
        /// </summary>
        protected internal override void GetDependentParts(MaterialUsage usage, IList <Type> result)
        {
            result.Add(typeof(MaterialParts.BeginPaintGroupMaterialPart));
            result.Add(typeof(MaterialParts.EndPaintGroupMaterialPart));

            var count = materialParts.Count;

            for (int i = 0; i < count; ++i)
            {
                materialParts[i].GetDependentParts(usage, result);
            }
        }
コード例 #13
0
        protected internal override string GetShaderCode(MaterialUsage usage)
        {
            // When using alpha test with transparent materials, don't write to depth.
            if (MaterialGroup.IsTransparent && (usage == MaterialUsage.Depth || usage == MaterialUsage.DepthAndNormal))
            {
                return(null);
            }

            bool eqne = (alphaFunction == CompareFunction.Equal || alphaFunction == CompareFunction.NotEqual);

            return(GetShaderCode("AlphaTest").Replace("{$EQNE}", eqne ? "" : "//").Replace("{$LTGT}", eqne ? "//" : ""));
        }
コード例 #14
0
        protected internal override void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance)
        {
            var part = ((DiffuseMaterialPart)existingInstance);

            part.Texture             = this.Texture;
            part.diffuseColor        = diffuseColor;
            part.diffuseColorEnabled = diffuseColorEnabled;
            part.overlayColor        = overlayColor;
            part.textureAlphaUsage   = textureAlphaUsage;
            part.textureEnabled      = textureEnabled;
            part.vertexColorEnabled  = vertexColorEnabled;
        }
コード例 #15
0
        protected override Material OnResolveMaterial(MaterialUsage usage, Material existingInstance)
        {
#if !WINDOWS_PHONE
            if (usage == MaterialUsage.Depth)
            {
                var result = (existingInstance as DepthMaterial) ?? new DepthMaterial(GraphicsDevice)
                {
                    AlphaTestEnabled = true
                };
                result.referenceAlpha = ReferenceAlpha;
                return(result);
            }
#endif
            return(null);
        }
コード例 #16
0
        protected internal override string GetShaderCode(MaterialUsage usage)
        {
            if (usage != MaterialUsage.Default && usage != MaterialUsage.Depth && usage != MaterialUsage.DepthAndNormal)
            {
                return(null);
            }

            return(GetShaderCode("DiffuseTexture").Replace("{$V1}", vertexColorEnabled ? "" : "//")
                   .Replace("{$V2}", vertexColorEnabled ? "//" : "")
                   .Replace("{$AO}", textureAlphaUsage == TextureAlphaUsage.Overlay ? "" : "//")
                   .Replace("{$AA}", textureAlphaUsage == TextureAlphaUsage.Opacity ? "" : "//")
                   .Replace("{$AN}", textureAlphaUsage == TextureAlphaUsage.None ? "" : "//")
                   .Replace("{$AS}", textureAlphaUsage == TextureAlphaUsage.Specular ? "" : "//")
                   .Replace("{$D1}", diffuseColorEnabled ? "" : "//")
                   .Replace("{$D2}", diffuseColorEnabled ? "//" : "")
                   .Replace("{$TE}", textureEnabled ? "" : "//"));
        }
コード例 #17
0
ファイル: MaterialGroup.cs プロジェクト: Hengle/Engine-Nine
        /// <summary>
        /// Gets the material with the specified usage that is attached to this material.
        /// </summary>
        protected override Material OnResolveMaterial(MaterialUsage usage, Material existingInstance)
        {
            var result = existingInstance as MaterialGroup;

            if (result == null && ExtendedMaterials != null)
            {
                result = ExtendedMaterials[(int)usage];
            }
            if (result == null)
            {
                return(null);
            }

            var srcCount  = materialParts.Count;
            var destCount = result.materialParts.Count;

            if (srcCount > 0 && destCount > 0)
            {
                var src      = 0;
                var dest     = 0;
                var srcPart  = materialParts[0];
                var destPart = result.materialParts[0];
                var srcType  = srcPart.GetType();
                var destType = destPart.GetType();

                // Source material parts is a super set of destination material parts.
                while (dest < destCount)
                {
                    destPart = result.materialParts[dest++];
                    destType = destPart.GetType();

                    while (src < srcCount)
                    {
                        srcPart = materialParts[src++];
                        srcType = srcPart.GetType();
                        if (srcType == destType)
                        {
                            srcPart.OnResolveMaterialPart(usage, destPart);
                            break;
                        }
                    }
                }
            }
            return(result);
        }
コード例 #18
0
        private Material ResolveMaterial(MaterialUsage usage, Material existingInstance)
        {
            var result = OnResolveMaterial(usage, existingInstance);

            if (result == null && MaterialResolve != null)
            {
                var listeners = MaterialResolve.GetInvocationList();
                for (int i = 0; i < listeners.Length; ++i)
                {
                    var resolve = (MaterialResolveEventHandler)listeners[i];
                    if (resolve != null && (result = resolve(this, usage, existingInstance)) != null)
                    {
                        break;
                    }
                }
            }
            return(result);
        }
コード例 #19
0
        /// <summary>
        /// Gets the shader code for this material part based on material usage.
        /// </summary>
        protected internal override string GetShaderCode(MaterialUsage usage)
        {
            if (!string.IsNullOrEmpty(ShaderCode))
            {
                if (usage == MaterialUsage.Default)
                {
                    return(ShaderCode);
                }
                if (shaderUsages != null && shaderUsages.Contains(usage))
                {
                    return(ShaderCode);
                }
            }
            string code = null;

            if (shaderCodes != null)
            {
                shaderCodes.TryGetValue(usage, out code);
            }
            return(code);
        }
コード例 #20
0
 protected internal override void GetDependentParts(MaterialUsage usage, IList<Type> result)
 {
     result.Add(typeof(EndLightMaterialPart));
 }
コード例 #21
0
ファイル: MaterialPart.cs プロジェクト: Hengle/Engine-Nine
 /// <summary>
 /// Gets the material with the specified usage that is attached to this material.
 /// </summary>
 protected internal virtual void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance)
 {
 }
コード例 #22
0
ファイル: MaterialPart.cs プロジェクト: Hengle/Engine-Nine
 /// <summary>
 /// Puts the dependent parts into the result list.
 /// </summary>
 protected internal virtual void GetDependentParts(MaterialUsage usage, IList <Type> result)
 {
 }
コード例 #23
0
ファイル: MaterialPart.cs プロジェクト: Hengle/Engine-Nine
 /// <summary>
 /// Gets the shader code for this material part based on material usage.
 /// </summary>
 protected internal abstract string GetShaderCode(MaterialUsage usage);
コード例 #24
0
 protected internal override string GetShaderCode(MaterialUsage usage)
 {
     return((usage == MaterialUsage.Default || usage == MaterialUsage.DepthAndNormal || usage == MaterialUsage.Normal) ? GetShaderCode("NormalMap") : null);
 }
コード例 #25
0
        protected internal override void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance)
        {
            var part = ((NormalMapMaterialPart)existingInstance);

            part.NormalMap = this.NormalMap;
        }
コード例 #26
0
 protected internal override void GetDependentParts(MaterialUsage usage, IList <Type> result)
 {
     result.Add(typeof(TangentTransformMaterialPart));
 }
コード例 #27
0
        private static bool BuildByUsage(MaterialGroup materialGroup, MaterialUsage usage, out byte[] effectCode, out byte[] key)
        {
            key = effectCode = null;

            // Make sure we have the necessary building blocks of a shader
            if (materialGroup.MaterialParts.Count <= 0)
            {
                materialGroup.MaterialParts.Add(new DiffuseMaterialPart()
                {
                    DiffuseColorEnabled = false, TextureEnabled = false
                });
            }

            var dependentPartTypes = new List <Type>();

            for (int p = 0; p < materialGroup.MaterialParts.Count; p++)
            {
                var currentPart = materialGroup.MaterialParts[p];
                currentPart.GetDependentParts(usage, dependentPartTypes);
                for (int i = 0; i < dependentPartTypes.Count; ++i)
                {
                    var type = dependentPartTypes[i];
                    if (!materialGroup.MaterialParts.Any(x => x.GetType() == type))
                    {
                        var part = (MaterialPart)Activator.CreateInstance(type);
                        part.GetDependentParts(usage, dependentPartTypes);
                        materialGroup.MaterialParts.Insert(++p, part);
                    }
                    else
                    {
                        var parts = materialGroup.MaterialParts.Where(x => x.GetType() == type && x != currentPart).ToArray();
                        foreach (var pt in parts)
                        {
                            materialGroup.MaterialParts.Remove(pt);
                        }
                        p = materialGroup.MaterialParts.IndexOf(currentPart);
                        foreach (var pt in parts)
                        {
                            materialGroup.MaterialParts.Insert(++p, pt);
                        }
                    }
                }
                dependentPartTypes.Clear();
            }

            if (!materialGroup.MaterialParts.OfType <VertexTransformMaterialPart>().Any())
            {
                materialGroup.MaterialParts.Add(new VertexTransformMaterialPart());
            }

            var builderContext = CreateMaterialGroupBuilderContext(materialGroup.MaterialParts, usage, true);

            if (builderContext.PixelShaderOutputs.Count <= 0)
            {
                return(false);
            }

            try
            {
                // Force 3_0 when using instancing
                if (materialGroup.MaterialParts.OfType <InstancedMaterialPart>().Any())
                {
                    throw new InvalidOperationException();
                }

                return(BuildEffect(builderContext, "2_0", out effectCode, out key));
            }
            catch
            {
                return(BuildEffect(builderContext, "3_0", out effectCode, out key));
            }
        }
コード例 #28
0
        private void Material_radioClick(object sender, EventArgs e)
        {
            // Check for the checked radiobutton, and set the Material Selection property.
            foreach (RadioButton radio in matsToUse.Controls.Cast<Control>().Select(control => control as RadioButton).Where(radio => radio.Checked))
                _materialSelection = (MaterialUsage)Convert.ToInt32(radio.Tag);

            // Call the method to populate the material string.
            SetMaterialUsage();
        }
コード例 #29
0
        internal static MaterialGroupBuilderContext CreateMaterialGroupBuilderContext(IList <MaterialPart> materialParts, MaterialUsage usage, bool simplify)
        {
            var builderContext = new MaterialGroupBuilderContext();

            // Step 1: Parse material part declarations from input material group.
            builderContext.MaterialPartDeclarations = new List <MaterialPartDeclaration>();
            foreach (var part in materialParts)
            {
                var code = part.GetShaderCode(usage);
                if (!string.IsNullOrEmpty(code))
                {
                    var newPart = new Lexer(code).Read();
                    newPart.MaterialPart = part;
                    builderContext.MaterialPartDeclarations.Add(newPart);
                }
            }

            builderContext.ArgumentDictionary = new Dictionary <string, ArgumentDeclaration>();

            foreach (var arg in (from part in builderContext.MaterialPartDeclarations select part.VertexShader).Concat(
                         from part in builderContext.MaterialPartDeclarations select part.PixelShader).OfType <FunctionDeclaration>()
                     .SelectMany(f => f.Arguments))
            {
                ArgumentDeclaration argument;
                if (builderContext.ArgumentDictionary.TryGetValue(arg.Name, out argument))
                {
                    if (argument.Type != arg.Type)
                    {
                        throw new InvalidOperationException(string.Format("Paramter {0} has two different types {1}, {2}", arg.Name, argument, arg.Type));
                    }

                    if (!string.IsNullOrEmpty(argument.Semantic))
                    {
                        if (!string.IsNullOrEmpty(arg.Semantic) && arg.Semantic != argument.Semantic)
                        {
                            throw new InvalidOperationException(string.Format("Paramter {0} has two different sementics {1}, {2}", arg.Name, argument, arg.Semantic));
                        }
                        arg.Semantic = argument.Semantic;
                    }
                    else if (!string.IsNullOrEmpty(arg.Semantic))
                    {
                        argument.Semantic = arg.Semantic;
                    }

                    if (!string.IsNullOrEmpty(argument.DefaultValue))
                    {
                        if (!string.IsNullOrEmpty(arg.DefaultValue) && arg.DefaultValue != argument.DefaultValue)
                        {
                            throw new InvalidOperationException(string.Format("Paramter {0} has two different default value {1}, {2}", arg.Name, argument, arg.DefaultValue));
                        }
                        arg.DefaultValue = argument.DefaultValue;
                    }
                    else if (!string.IsNullOrEmpty(arg.DefaultValue))
                    {
                        argument.DefaultValue = arg.DefaultValue;
                    }
                }
                else
                {
                    builderContext.ArgumentDictionary.Add(arg.Name, arg);
                }
            }

            foreach (var arg in builderContext.ArgumentDictionary.Values)
            {
                arg.DefaultValue = arg.DefaultValue ?? "0";
            }


            // Step 2: Figure out the dependencies of material parts based on function input arguments
            Regex validPixelShaderOutputSemantic;
            Regex validVertexShaderOutputSemantic;

            validPixelShaderOutputSemantic  = new Regex("^COLOR[0-9]$");
            validVertexShaderOutputSemantic = new Regex("^(COLOR[0-9]+)|(POSITION[0-9]+)|(TEXCOORD[0-9]+)$");

            var psOutputSemantics = new List <string>();
            var vsOutputSemantics = new List <string>();

            for (int i = builderContext.MaterialPartDeclarations.Count - 1; i >= 0; i--)
            {
                var part = builderContext.MaterialPartDeclarations[i];
                part.Index = i;
                part.MaterialPart.ParameterSuffix = string.Concat("_", i);

                if (part.VertexShader != null)
                {
                    var vsOutputArgs = part.VertexShader.Arguments.Where(a => a != null && a.Semantic != null && a.Out && validVertexShaderOutputSemantic.IsMatch(a.Semantic)).Select(a => a.Semantic).ToArray();
                    if (vsOutputArgs.Length > 0 && !vsOutputSemantics.Intersect(vsOutputArgs).Any())
                    {
                        vsOutputSemantics.AddRange(vsOutputArgs);
                        part.IsVertexShaderOutput = true;
                    }
                }

                if (part.PixelShader != null)
                {
                    var psOutputArgs = part.PixelShader.Arguments.Where(a => a != null && a.Semantic != null && a.Out && validPixelShaderOutputSemantic.IsMatch(a.Semantic)).Select(a => a.Semantic).ToArray();
                    if (psOutputArgs.Length > 0 && !psOutputSemantics.Intersect(psOutputArgs).Any())
                    {
                        psOutputSemantics.AddRange(psOutputArgs);
                        part.IsPixelShaderOutput = true;
                    }
                }
            }

            foreach (var materialDeclaration in builderContext.MaterialPartDeclarations)
            {
                materialDeclaration.Dependencies =
                    (from part in builderContext.MaterialPartDeclarations
                     where part != materialDeclaration && part.VertexShader != null &&
                     part.VertexShader.Arguments.Any(arg => arg.Out && (!arg.In || part.Index < materialDeclaration.Index) &&
                                                     materialDeclaration.VertexShader != null && materialDeclaration.VertexShader.Arguments.Any(a => a.In && a.Name == arg.Name))
                     select part).Concat
                        (from part in builderContext.MaterialPartDeclarations
                        where part != materialDeclaration && part.PixelShader != null &&
                        part.PixelShader.Arguments.Any(arg => arg.Out && (!arg.In || part.Index < materialDeclaration.Index) &&
                                                       materialDeclaration.PixelShader != null && materialDeclaration.PixelShader.Arguments.Any(a => a.In && a.Name == arg.Name))
                        select part).Concat
                        (from part in builderContext.MaterialPartDeclarations
                        where part != materialDeclaration && part.VertexShader != null &&
                        part.VertexShader.Arguments.Any(arg => arg.Out &&
                                                        materialDeclaration.PixelShader != null && materialDeclaration.PixelShader.Arguments.Any(a => a.In && a.Name == arg.Name))
                        select part).ToArray();
            }

            // Step 3: Dependency sorting
            int[] order = new int[builderContext.MaterialPartDeclarations.Count];
            DependencyGraph.Sort(builderContext.MaterialPartDeclarations, order, new MaterialPartDeclarationDependencyProvider());
            builderContext.MaterialPartDeclarations = order.Select(i => builderContext.MaterialPartDeclarations[i]).ToList();

            // Remove pixel shader parts that don't have a path to the pixel shader output
            foreach (var part in Enumerable.Reverse(builderContext.MaterialPartDeclarations))
            {
                if (!simplify || part.IsPixelShaderOutput || part.Tagged || (part.PixelShader != null && part.PixelShader.ContainsClip))
                {
                    part.Tagged = true;
                    foreach (var d in part.Dependencies)
                    {
                        d.Tagged = true;
                    }
                }
            }

            builderContext.MaterialPartDeclarations = (from part in builderContext.MaterialPartDeclarations where part.Tagged || part.PixelShader == null select part).ToList();

            // Step 4: Get shader input/output argument semantics
            var argumentEqualtyComparer = new ArgumentDeclarationEqualyComparer();

            builderContext.VertexShaderInputs  = new List <ArgumentDeclaration>();
            builderContext.VertexShaderOutputs = new List <ArgumentDeclaration>();

            for (int i = 0; i < builderContext.MaterialPartDeclarations.Count; ++i)
            {
                if (builderContext.MaterialPartDeclarations[i].VertexShader != null)
                {
                    builderContext.VertexShaderInputs.AddRange(from arg in builderContext.MaterialPartDeclarations[i].VertexShader.Arguments
                                                               where arg.In && !builderContext.MaterialPartDeclarations.Take(i).Select(p => p.VertexShader)
                                                               .OfType <FunctionDeclaration>().SelectMany(f => f.Arguments)
                                                               .Any(a => a.Out && a.Name == arg.Name)
                                                               select arg);

                    builderContext.VertexShaderOutputs.AddRange(from arg in builderContext.MaterialPartDeclarations[i].VertexShader.Arguments
                                                                where arg.Out && !builderContext.MaterialPartDeclarations.Skip(i + 1).Select(p => p.VertexShader)
                                                                .OfType <FunctionDeclaration>().SelectMany(f => f.Arguments)
                                                                .Any(a => a.In && a.Name == arg.Name)
                                                                select arg);
                }
            }

            builderContext.PixelShaderInputs  = new List <ArgumentDeclaration>();
            builderContext.PixelShaderOutputs = new List <ArgumentDeclaration>();

            for (int i = 0; i < builderContext.MaterialPartDeclarations.Count; ++i)
            {
                if (builderContext.MaterialPartDeclarations[i].PixelShader != null)
                {
                    builderContext.PixelShaderInputs.AddRange(from arg in builderContext.MaterialPartDeclarations[i].PixelShader.Arguments
                                                              where arg.In && !builderContext.MaterialPartDeclarations.Take(i).Select(p => p.PixelShader)
                                                              .OfType <FunctionDeclaration>().SelectMany(f => f.Arguments)
                                                              .Any(a => a.Out && a.Name == arg.Name)
                                                              select arg);

                    builderContext.PixelShaderOutputs.AddRange(from arg in builderContext.MaterialPartDeclarations[i].PixelShader.Arguments
                                                               where arg.Out && !builderContext.MaterialPartDeclarations.Skip(i + 1).Select(p => p.PixelShader)
                                                               .OfType <FunctionDeclaration>().SelectMany(f => f.Arguments)
                                                               .Any(a => a.In && a.Name == arg.Name)
                                                               select arg);
                }
            }

            builderContext.PixelShaderInputs   = builderContext.PixelShaderInputs.Distinct(argumentEqualtyComparer).ToList();
            builderContext.PixelShaderOutputs  = builderContext.PixelShaderOutputs.Distinct(argumentEqualtyComparer).ToList();
            builderContext.VertexShaderInputs  = builderContext.VertexShaderInputs.Distinct(argumentEqualtyComparer).ToList();
            builderContext.VertexShaderOutputs = builderContext.VertexShaderOutputs.Distinct(argumentEqualtyComparer).ToList();

            builderContext.PixelShaderInputs.ForEach(a => a.DefaultValue   = builderContext.ArgumentDictionary[a.Name].DefaultValue);
            builderContext.PixelShaderOutputs.ForEach(a => a.DefaultValue  = builderContext.ArgumentDictionary[a.Name].DefaultValue);
            builderContext.VertexShaderInputs.ForEach(a => a.DefaultValue  = builderContext.ArgumentDictionary[a.Name].DefaultValue);
            builderContext.VertexShaderOutputs.ForEach(a => a.DefaultValue = builderContext.ArgumentDictionary[a.Name].DefaultValue);

            // Step 5: Argument simplification and validation
            builderContext.TemporaryPixelShaderVariables = (from arg in builderContext.PixelShaderOutputs
                                                            where simplify && (arg.Semantic == null || !validPixelShaderOutputSemantic.IsMatch(arg.Semantic)) &&
                                                            !builderContext.PixelShaderInputs.Any(psi => psi.Name == arg.Name)
                                                            select arg).ToList();

            // Remove duplicated pixel shader output semantics, keep only the last one.
            for (int i = 0; i < builderContext.PixelShaderOutputs.Count; ++i)
            {
                if (builderContext.PixelShaderOutputs.Skip(i + 1).Any(a => a.Semantic == builderContext.PixelShaderOutputs[i].Semantic))
                {
                    builderContext.TemporaryPixelShaderVariables.Add(builderContext.PixelShaderOutputs[i]);
                    foreach (var psi in builderContext.PixelShaderInputs.Where(p => p.Name == builderContext.PixelShaderOutputs[i].Name))
                    {
                        psi.Out = false;
                    }
                    builderContext.PixelShaderOutputs.RemoveAt(i);
                    i--;
                }
            }

            // Pixel shader inputs that does not have a matching vertex shader output and a valid semantic
            for (int i = 0; i < builderContext.PixelShaderInputs.Count; ++i)
            {
                var psi = builderContext.PixelShaderInputs[i];
                if (builderContext.VertexShaderOutputs.Any(vso => vso.Name == psi.Name))
                {
                    continue;
                }
                if (string.IsNullOrEmpty(psi.Semantic))
                {
                    builderContext.TemporaryPixelShaderVariables.Add(psi);
                    builderContext.PixelShaderInputs.RemoveAt(i--);
                }
                else
                {
                    var arg = new ArgumentDeclaration {
                        Name = psi.Name, Type = psi.Type, Semantic = psi.Semantic, In = true, Out = true
                    };
                    if (!builderContext.VertexShaderInputs.Any(vsi => vsi.Name == psi.Name))
                    {
                        builderContext.VertexShaderInputs.Add(arg);
                    }
                    else
                    {
                        builderContext.VertexShaderInputs.Where(vsi => vsi.Name == psi.Name).ForEach(vsi => vsi.Out = true);
                    }
                    builderContext.VertexShaderOutputs.Add(arg);
                }
            }

            // Remove temporary duplicates
            builderContext.TemporaryPixelShaderVariables = builderContext.TemporaryPixelShaderVariables.Distinct(argumentEqualtyComparer).ToList();

            // Valid vertex shader input semantic
            foreach (var input in builderContext.VertexShaderInputs)
            {
                if (string.IsNullOrEmpty(input.Semantic))
                {
                    throw new InvalidOperationException(string.Concat("Cannot find semantics for vertex shader input ", input.Name));
                }
            }

            // Remove vertex shader outputs that do not have a corresponding pixel shader input
            builderContext.VertexShaderOutputs.RemoveAll(vso => vso.Semantic != "POSITION0" && !builderContext.PixelShaderInputs.Any(psi => psi.Name == vso.Name));

            // Expand vertex shader outputs that do not have a valid semantic
            var nextValidSemanticIndex = 0;

            builderContext.VertexShaderOutputSemanticMapping = builderContext.VertexShaderOutputs.Where(vso => vso.Semantic == null || !validVertexShaderOutputSemantic.IsMatch(vso.Semantic))
                                                               .ToDictionary(arg => arg, arg => NextValidSemantic(builderContext.VertexShaderOutputs, ref nextValidSemanticIndex));

            // POSITION0 is not a valid pixel shader input semantics
            if (builderContext.PixelShaderInputs.Any(psi => psi.Semantic == "POSITION0"))
            {
                var vso = builderContext.VertexShaderOutputs.Single(a => a.Semantic == "POSITION0");
                var arg = new ArgumentDeclaration()
                {
                    Out  = true,
                    Name = vso.Name + "_pos0_",
                    Type = vso.Type,
                };
                var semantic = NextValidSemantic(builderContext.VertexShaderOutputs, ref nextValidSemanticIndex);
                builderContext.VertexShaderOutputSemanticMapping.Add(arg, semantic);
                builderContext.PixelShaderInputs.Single(psi => psi.Semantic == "POSITION0").Semantic = semantic;
            }

            builderContext.VertexShaderOutputs.RemoveAll(vso => builderContext.VertexShaderOutputSemanticMapping.Any(m => m.Key.Name == vso.Name));
            builderContext.VertexShaderOutputs.RemoveAll(vso => builderContext.VertexShaderInputs.Any(vsi => vsi.Name == vso.Name && vsi.Out));

            if (builderContext.VertexShaderOutputs.Any(vso => vso.Semantic == "POSITION0"))
            {
                builderContext.VertexShaderInputs.Where(vsi => vsi.Semantic == "POSITION0").ForEach(vsi => vsi.Out = false);
            }

            // Fix vertex shader input modifier based on the above mapping
            foreach (var vsi in builderContext.VertexShaderInputs)
            {
                if ((!builderContext.PixelShaderInputs.Any(psi => psi.Name == vsi.Name) && vsi.Semantic != "POSITION0") ||
                    builderContext.VertexShaderOutputSemanticMapping.Any(p => vsi.Name == p.Key.Name))
                {
                    vsi.Out = false;
                }
            }

            // Fix pixel shader input semantics based on the above mapping
            foreach (var psi in builderContext.PixelShaderInputs)
            {
                psi.Out = builderContext.PixelShaderOutputs.Any(pso => pso.Name == psi.Name);
                foreach (var p in builderContext.VertexShaderOutputSemanticMapping)
                {
                    if (psi.Name == p.Key.Name)
                    {
                        psi.Semantic = p.Value;
                        break;
                    }
                }
            }
            builderContext.PixelShaderOutputs.RemoveAll(pso => builderContext.PixelShaderInputs.Any(psi => psi.Name == pso.Name) || builderContext.TemporaryPixelShaderVariables.Any(t => t.Name == pso.Name));
            if (simplify)
            {
                foreach (var psi in builderContext.PixelShaderInputs)
                {
                    psi.Out = false;
                }
            }

            // Merge vertex shader inout parameters
            builderContext.VertexShaderOutputs.RemoveAll(vso => vso.In && builderContext.VertexShaderInputs.Any(vsi => vsi.Name == vso.Name));
            return(builderContext);
        }
コード例 #30
0
 /// <summary>
 /// Gets the material with the specified usage that is attached to this material.
 /// </summary>
 protected virtual Material OnResolveMaterial(MaterialUsage usage, Material existingInstance)
 {
     return(null);
 }
コード例 #31
0
 protected internal override string GetShaderCode(MaterialUsage usage)
 {
     return(usage == MaterialUsage.Default ? GetShaderCode("BeginLight") : null);
 }