/// <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); }
protected internal override string GetShaderCode(MaterialUsage usage) { if (usage != MaterialUsage.Default) return null; return GetShaderCode("ShadowMap").Replace("{$SAMPLECOUNT}", (filterSize * filterSize).ToString()) .Replace("{$FILTERTAPS}", CreateFilterTaps()); }
protected internal override void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance) { var part = ((AlphaTestMaterialPart)existingInstance); part.ReferenceAlpha = ReferenceAlpha; part.alphaFunction = alphaFunction; }
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()); }
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); }
/// <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; } } } } }
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); }
protected internal override void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance) { var part = (BeginPaintGroupMaterialPart)existingInstance; part.maskTexture0 = maskTexture0; part.maskTexture1 = maskTexture1; part.maskTextureScale = maskTextureScale; }
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); }
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 ? "" : "//")); }
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)); } }
/// <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); } }
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 ? "//" : "")); }
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; }
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); }
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 ? "" : "//")); }
/// <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); }
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); }
/// <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); }
protected internal override void GetDependentParts(MaterialUsage usage, IList<Type> result) { result.Add(typeof(EndLightMaterialPart)); }
/// <summary> /// Gets the material with the specified usage that is attached to this material. /// </summary> protected internal virtual void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance) { }
/// <summary> /// Puts the dependent parts into the result list. /// </summary> protected internal virtual void GetDependentParts(MaterialUsage usage, IList <Type> result) { }
/// <summary> /// Gets the shader code for this material part based on material usage. /// </summary> protected internal abstract string GetShaderCode(MaterialUsage usage);
protected internal override string GetShaderCode(MaterialUsage usage) { return((usage == MaterialUsage.Default || usage == MaterialUsage.DepthAndNormal || usage == MaterialUsage.Normal) ? GetShaderCode("NormalMap") : null); }
protected internal override void OnResolveMaterialPart(MaterialUsage usage, MaterialPart existingInstance) { var part = ((NormalMapMaterialPart)existingInstance); part.NormalMap = this.NormalMap; }
protected internal override void GetDependentParts(MaterialUsage usage, IList <Type> result) { result.Add(typeof(TangentTransformMaterialPart)); }
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)); } }
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(); }
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); }
/// <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); }
protected internal override string GetShaderCode(MaterialUsage usage) { return(usage == MaterialUsage.Default ? GetShaderCode("BeginLight") : null); }