private static HashSet <string> GetActiveFieldsFromMasterNode(AbstractMaterialNode iMasterNode, Pass pass) { HashSet <string> activeFields = new HashSet <string>(); HDUnlitMasterNode masterNode = iMasterNode as HDUnlitMasterNode; if (masterNode == null) { return(activeFields); } if (masterNode.alphaTest.isOn && pass.PixelShaderUsesSlot(HDUnlitMasterNode.AlphaThresholdSlotId)) { activeFields.Add("AlphaTest"); } if (masterNode.surfaceType != SurfaceType.Opaque) { if (masterNode.transparencyFog.isOn) { activeFields.Add("AlphaFog"); } } return(activeFields); }
private static HashSet <string> GetActiveFieldsFromMasterNode(INode iMasterNode, Pass pass) { HashSet <string> activeFields = new HashSet <string>(); HDUnlitMasterNode masterNode = iMasterNode as HDUnlitMasterNode; if (masterNode == null) { return(activeFields); } if (masterNode.alphaTest.isOn && pass.PixelShaderUsesSlot(HDUnlitMasterNode.AlphaThresholdSlotId)) { activeFields.Add("AlphaTest"); } if (masterNode.surfaceType != SurfaceType.Opaque) { activeFields.Add("SurfaceType.Transparent"); if (masterNode.alphaMode == AlphaMode.Alpha) { activeFields.Add("BlendMode.Alpha"); } else if (masterNode.alphaMode == AlphaMode.Premultiply) { activeFields.Add("BlendMode.Premultiply"); } else if (masterNode.alphaMode == AlphaMode.Additive) { activeFields.Add("BlendMode.Add"); } if (masterNode.transparencyFog.isOn) { activeFields.Add("AlphaFog"); } } return(activeFields); }
private static HashSet <string> GetActiveFieldsFromMasterNode(INode iMasterNode, Pass pass) { HashSet <string> activeFields = new HashSet <string>(); HDLitMasterNode masterNode = iMasterNode as HDLitMasterNode; if (masterNode == null) { return(activeFields); } if (masterNode.doubleSidedMode != DoubleSidedMode.Disabled) { activeFields.Add("DoubleSided"); if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system { // we need to be able to build interpolators using multiple input structs // also: should only require isFrontFace if Normals are required... if (masterNode.doubleSidedMode == DoubleSidedMode.FlippedNormals) { activeFields.Add("DoubleSided.Flip"); } else if (masterNode.doubleSidedMode == DoubleSidedMode.MirroredNormals) { activeFields.Add("DoubleSided.Mirror"); } // Important: the following is used in SharedCode.template.hlsl for determining the normal flip mode activeFields.Add("FragInputs.isFrontFace"); } } switch (masterNode.materialType) { case HDLitMasterNode.MaterialType.Anisotropy: activeFields.Add("Material.Anisotropy"); break; case HDLitMasterNode.MaterialType.Iridescence: activeFields.Add("Material.Iridescence"); break; case HDLitMasterNode.MaterialType.SpecularColor: activeFields.Add("Material.SpecularColor"); break; case HDLitMasterNode.MaterialType.Standard: activeFields.Add("Material.Standard"); break; case HDLitMasterNode.MaterialType.SubsurfaceScattering: { if (masterNode.surfaceType != SurfaceType.Transparent) { activeFields.Add("Material.SubsurfaceScattering"); } if (masterNode.sssTransmission.isOn) { activeFields.Add("Material.Transmission"); } } break; case HDLitMasterNode.MaterialType.Translucent: { activeFields.Add("Material.Translucent"); activeFields.Add("Material.Transmission"); } break; default: UnityEngine.Debug.LogError("Unknown material type: " + masterNode.materialType); break; } if (masterNode.alphaTest.isOn) { int count = 0; // If alpha test shadow is enable, we use it, otherwise we use the regular test if (pass.PixelShaderUsesSlot(HDLitMasterNode.AlphaThresholdShadowSlotId) && masterNode.alphaTestShadow.isOn) { activeFields.Add("AlphaTestShadow"); ++count; } else if (pass.PixelShaderUsesSlot(HDLitMasterNode.AlphaThresholdSlotId)) { activeFields.Add("AlphaTest"); ++count; } if (pass.PixelShaderUsesSlot(HDLitMasterNode.AlphaThresholdDepthPrepassSlotId)) { activeFields.Add("AlphaTestPrepass"); ++count; } if (pass.PixelShaderUsesSlot(HDLitMasterNode.AlphaThresholdDepthPostpassSlotId)) { activeFields.Add("AlphaTestPostpass"); ++count; } UnityEngine.Debug.Assert(count == 1, "Alpha test value not set correctly"); } if (masterNode.surfaceType != SurfaceType.Opaque) { activeFields.Add("SurfaceType.Transparent"); if (masterNode.alphaMode == AlphaMode.Alpha) { activeFields.Add("BlendMode.Alpha"); } else if (masterNode.alphaMode == AlphaMode.Premultiply) { activeFields.Add("BlendMode.Premultiply"); } else if (masterNode.alphaMode == AlphaMode.Additive) { activeFields.Add("BlendMode.Add"); } if (masterNode.blendPreserveSpecular.isOn) { activeFields.Add("BlendMode.PreserveSpecular"); } if (masterNode.transparencyFog.isOn) { activeFields.Add("AlphaFog"); } } if (!masterNode.receiveDecals.isOn) { activeFields.Add("DisableDecals"); } if (!masterNode.receiveSSR.isOn) { activeFields.Add("DisableSSR"); } if (masterNode.specularAA.isOn && pass.PixelShaderUsesSlot(HDLitMasterNode.SpecularAAThresholdSlotId) && pass.PixelShaderUsesSlot(HDLitMasterNode.SpecularAAScreenSpaceVarianceSlotId)) { activeFields.Add("Specular.AA"); } if (masterNode.energyConservingSpecular.isOn) { activeFields.Add("Specular.EnergyConserving"); } if (masterNode.HasRefraction()) { activeFields.Add("Refraction"); switch (masterNode.refractionModel) { case ScreenSpaceRefraction.RefractionModel.Box: activeFields.Add("RefractionBox"); break; case ScreenSpaceRefraction.RefractionModel.Sphere: activeFields.Add("RefractionSphere"); break; default: UnityEngine.Debug.LogError("Unknown refraction model: " + masterNode.refractionModel); break; } } if (masterNode.IsSlotConnected(HDLitMasterNode.BentNormalSlotId) && pass.PixelShaderUsesSlot(HDLitMasterNode.BentNormalSlotId)) { activeFields.Add("BentNormal"); } if (masterNode.IsSlotConnected(HDLitMasterNode.TangentSlotId) && pass.PixelShaderUsesSlot(HDLitMasterNode.TangentSlotId)) { activeFields.Add("Tangent"); } switch (masterNode.specularOcclusionMode) { case SpecularOcclusionMode.Off: break; case SpecularOcclusionMode.FromAO: activeFields.Add("SpecularOcclusionFromAO"); break; case SpecularOcclusionMode.FromAOAndBentNormal: activeFields.Add("SpecularOcclusionFromAOBentNormal"); break; case SpecularOcclusionMode.Custom: activeFields.Add("SpecularOcclusionCustom"); break; default: break; } if (pass.PixelShaderUsesSlot(HDLitMasterNode.AmbientOcclusionSlotId)) { var occlusionSlot = masterNode.FindSlot <Vector1MaterialSlot>(HDLitMasterNode.AmbientOcclusionSlotId); bool connected = masterNode.IsSlotConnected(HDLitMasterNode.AmbientOcclusionSlotId); if (connected || occlusionSlot.value != occlusionSlot.defaultValue) { activeFields.Add("AmbientOcclusion"); } } if (pass.PixelShaderUsesSlot(HDLitMasterNode.CoatMaskSlotId)) { var coatMaskSlot = masterNode.FindSlot <Vector1MaterialSlot>(HDLitMasterNode.CoatMaskSlotId); bool connected = masterNode.IsSlotConnected(HDLitMasterNode.CoatMaskSlotId); if (connected || coatMaskSlot.value > 0.0f) { activeFields.Add("CoatMask"); } } return(activeFields); }
// // Reference for GetActiveFieldsFromMasterNode // ------------------------------------------- // // Properties (enables etc): // // ok+MFD -> material feature define: means we need a predicate, because we will transform it into a #define that match the material feature, shader_feature-defined, that the rest of the shader code uses. // // ok+MFD masterNode.baseParametrization --> even though we can just always transfer present fields (check with $SurfaceDescription.*) like specularcolor and metallic, // we need to translate this into the _MATERIAL_FEATURE_SPECULAR_COLOR define. // // ok masterNode.energyConservingSpecular // // ~~~~ ok+MFD: these are almost all material features: // masterNode.anisotropy // masterNode.coat // masterNode.coatNormal // masterNode.dualSpecularLobe // masterNode.dualSpecularLobeParametrization // masterNode.capHazinessWrtMetallic -> not a material feature define, as such, we will create a combined predicate for the HazyGlossMaxDielectricF0 slot dependency // instead of adding a #define in the template... // masterNode.iridescence // masterNode.subsurfaceScattering // masterNode.transmission // // ~~~~ ...ok+MFD: these are all material features // // ok masterNode.receiveDecals // ok masterNode.receiveSSR // ok masterNode.geometricSpecularAA --> check, a way to combine predicates and/or exclude passes: TODOTODO What about WRITE_NORMAL_BUFFER passes ? (ie smoothness) // ok masterNode.specularOcclusion --> no use for it though! see comments. // // ~~~~ ok+D: these require translation to defines also... // // masterNode.anisotropyForAreaLights // masterNode.recomputeStackPerLight // masterNode.shadeBaseUsingRefractedAngles // masterNode.debug // Inputs: Most inputs don't need a specific predicate in addition to the "present field predicate", ie the $SurfaceDescription.*, // but in some special cases we check connectivity to avoid processing the default value for nothing... // (see specular occlusion with _MASKMAP and _BENTNORMALMAP in LitData, or _TANGENTMAP, _BENTNORMALMAP, etc. which act a bit like that // although they also avoid sampling in that case, but default tiny texture map sampling isn't a big hit since they are all cached once // a default "unityTexWhite" is sampled, it is cached for everyone defaulting to white...) // // ok+ means there's a specific additional predicate // // ok masterNode.BaseColorSlotId // ok masterNode.NormalSlotId // // ok+ masterNode.BentNormalSlotId --> Dependency of the predicate on IsSlotConnected avoids processing even if the slots // ok+ masterNode.TangentSlotId are always there so any pass that declares its use in PixelShaderSlots will have the field in SurfaceDescription, // but it's not necessarily useful (if slot isnt connected, waste processing on potentially static expressions if // shader compiler cant optimize...and even then, useless to have static override value for those.) // // TODOTODO: Note you could have the same argument for NormalSlot (which we dont exclude with a predicate). // Also and anyways, the compiler is smart enough not to do the TS to WS matrix multiply on a (0,0,1) vector. // // ok+ masterNode.CoatNormalSlotId -> we already have a "material feature" coat normal map so can use that instead, although using that former, we assume the coat normal slot // will be there, but it's ok, we can #ifdef the code on the material feature define, and use the $SurfaceDescription.CoatNormal predicate // for the actual assignment, // although for that one we could again // use the "connected" condition like for tangent and bentnormal // // The following are all ok, no need beyond present field predicate, ie $SurfaceDescription.*, // except special cases where noted // // ok masterNode.SubsurfaceMaskSlotId // ok masterNode.ThicknessSlotId // ok masterNode.DiffusionProfileHashSlotId // ok masterNode.IridescenceMaskSlotId // ok masterNode.IridescenceThicknessSlotId // ok masterNode.SpecularColorSlotId // ok masterNode.DielectricIorSlotId // ok masterNode.MetallicSlotId // ok masterNode.EmissionSlotId // ok masterNode.SmoothnessASlotId // ok masterNode.SmoothnessBSlotId // ok+ masterNode.AmbientOcclusionSlotId -> defined a specific predicate, but not used, see StackLitData. // ok masterNode.AlphaSlotId // ok masterNode.AlphaClipThresholdSlotId // ok masterNode.AnisotropyASlotId // ok masterNode.AnisotropyBSlotId // ok masterNode.SpecularAAScreenSpaceVarianceSlotId // ok masterNode.SpecularAAThresholdSlotId // ok masterNode.CoatSmoothnessSlotId // ok masterNode.CoatIorSlotId // ok masterNode.CoatThicknessSlotId // ok masterNode.CoatExtinctionSlotId // ok masterNode.LobeMixSlotId // ok masterNode.HazinessSlotId // ok masterNode.HazeExtentSlotId // ok masterNode.HazyGlossMaxDielectricF0SlotId -> No need for a predicate, the needed predicate is the combined (capHazinessWrtMetallic + HazyGlossMaxDielectricF0) // "leaking case": if the 2 are true, but we're not in metallic mode, the capHazinessWrtMetallic property is wrong, // that means the master node is really misconfigured, spew an error, should never happen... // If it happens, it's because we forgot UpdateNodeAfterDeserialization() call when modifying the capHazinessWrtMetallic or baseParametrization // properties, maybe through debug etc. // // ok masterNode.DistortionSlotId -> Warning: peculiarly, instead of using $SurfaceDescription.Distortion and DistortionBlur, // ok masterNode.DistortionBlurSlotId we do an #if (SHADERPASS == SHADERPASS_DISTORTION) in the template, instead of // relying on other passed NOT to include the DistortionSlotId in their PixelShaderSlots!! // Other to deal with, and // Common between Lit and StackLit: // // doubleSidedMode, alphaTest, receiveDecals, // surfaceType, alphaMode, blendPreserveSpecular, transparencyFog, // distortion, distortionMode, distortionDepthTest, // sortPriority (int) // geometricSpecularAA, energyConservingSpecular, specularOcclusion // private static HashSet <string> GetActiveFieldsFromMasterNode(AbstractMaterialNode iMasterNode, Pass pass) { HashSet <string> activeFields = new HashSet <string>(); StackLitMasterNode masterNode = iMasterNode as StackLitMasterNode; if (masterNode == null) { return(activeFields); } if (masterNode.doubleSidedMode != DoubleSidedMode.Disabled) { activeFields.Add("DoubleSided"); if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system { // we need to be able to build interpolators using multiple input structs // also: should only require isFrontFace if Normals are required... if (masterNode.doubleSidedMode == DoubleSidedMode.FlippedNormals) { activeFields.Add("DoubleSided.Flip"); } else if (masterNode.doubleSidedMode == DoubleSidedMode.MirroredNormals) { activeFields.Add("DoubleSided.Mirror"); } // Important: the following is used in SharedCode.template.hlsl for determining the normal flip mode activeFields.Add("FragInputs.isFrontFace"); } } if (masterNode.alphaTest.isOn) { if (pass.PixelShaderUsesSlot(StackLitMasterNode.AlphaClipThresholdSlotId)) { activeFields.Add("AlphaTest"); } } if (masterNode.surfaceType != SurfaceType.Opaque) { activeFields.Add("SurfaceType.Transparent"); if (masterNode.alphaMode == AlphaMode.Alpha) { activeFields.Add("BlendMode.Alpha"); } else if (masterNode.alphaMode == AlphaMode.Premultiply) { activeFields.Add("BlendMode.Premultiply"); } else if (masterNode.alphaMode == AlphaMode.Additive) { activeFields.Add("BlendMode.Add"); } if (masterNode.blendPreserveSpecular.isOn) { activeFields.Add("BlendMode.PreserveSpecular"); } if (masterNode.transparencyFog.isOn) { activeFields.Add("AlphaFog"); } } // // Predicates to change into defines: // // Even though we can just always transfer the present (check with $SurfaceDescription.*) fields like specularcolor // and metallic, we still need to know the baseParametrization in the template to translate into the // _MATERIAL_FEATURE_SPECULAR_COLOR define: if (masterNode.baseParametrization == StackLit.BaseParametrization.SpecularColor) { activeFields.Add("BaseParametrization.SpecularColor"); } if (masterNode.energyConservingSpecular.isOn) // No defines, suboption of BaseParametrization.SpecularColor { activeFields.Add("EnergyConservingSpecular"); } if (masterNode.anisotropy.isOn) { activeFields.Add("Material.Anisotropy"); } if (masterNode.coat.isOn) { activeFields.Add("Material.Coat"); } if (masterNode.coatNormal.isOn) { activeFields.Add("Material.CoatNormal"); } if (masterNode.dualSpecularLobe.isOn) { activeFields.Add("Material.DualSpecularLobe"); if (masterNode.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.HazyGloss) { activeFields.Add("DualSpecularLobeParametrization.HazyGloss"); // Option for baseParametrization == Metallic && DualSpecularLobeParametrization == HazyGloss: if (masterNode.capHazinessWrtMetallic.isOn && pass.PixelShaderUsesSlot(StackLitMasterNode.HazyGlossMaxDielectricF0SlotId)) { // check the supporting slot is there (although masternode should deal with having a consistent property config) var maxDielectricF0Slot = masterNode.FindSlot <Vector1MaterialSlot>(StackLitMasterNode.HazyGlossMaxDielectricF0SlotId); if (maxDielectricF0Slot != null) { // Again we assume masternode has HazyGlossMaxDielectricF0 which should always be the case // if capHazinessWrtMetallic.isOn. activeFields.Add("CapHazinessIfNotMetallic"); } } } } if (masterNode.iridescence.isOn) { activeFields.Add("Material.Iridescence"); } if (masterNode.subsurfaceScattering.isOn && masterNode.surfaceType != SurfaceType.Transparent) { activeFields.Add("Material.SubsurfaceScattering"); } if (masterNode.transmission.isOn) { activeFields.Add("Material.Transmission"); } // Advanced: if (masterNode.anisotropyForAreaLights.isOn) { activeFields.Add("AnisotropyForAreaLights"); } if (masterNode.recomputeStackPerLight.isOn) { activeFields.Add("RecomputeStackPerLight"); } if (masterNode.shadeBaseUsingRefractedAngles.isOn) { activeFields.Add("ShadeBaseUsingRefractedAngles"); } if (masterNode.debug.isOn) { activeFields.Add("StackLitDebug"); } // // Other property predicates: // if (!masterNode.receiveDecals.isOn) { activeFields.Add("DisableDecals"); } if (!masterNode.receiveSSR.isOn) { activeFields.Add("DisableSSR"); } // Note here we combine an "enable"-like predicate and the $SurfaceDescription.(slotname) predicate // into a single $GeometricSpecularAA pedicate. // // ($SurfaceDescription.* predicates are useful to make sure the field is present in the struct in the template. // The field will be present if both the master node and pass have the slotid, see this set intersection we make // in GenerateSurfaceDescriptionStruct(), with HDSubShaderUtilities.FindMaterialSlotsOnNode().) // // Normally, since the feature enable adds the required slots, only the $SurfaceDescription.* would be required, // but some passes might not need it and not declare the PixelShaderSlot, or, inversely, the pass might not // declare it as a way to avoid it. // // IE this has also the side effect to disable geometricSpecularAA - even if "on" - for passes that don't explicitly // advertise these slots(eg for a general feature, with separate "enable" and "field present" predicates, the // template could take a default value and process it anyway if a feature is "on"). // // (Note we can achieve the same results in the template on just single predicates by making defines out of them, // and using #if defined() && etc) bool haveSomeSpecularAA = false; // TODOTODO in prevision of normal texture filtering if (masterNode.geometricSpecularAA.isOn && pass.PixelShaderUsesSlot(StackLitMasterNode.SpecularAAThresholdSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.SpecularAAScreenSpaceVarianceSlotId)) { haveSomeSpecularAA = true; activeFields.Add("GeometricSpecularAA"); } if (haveSomeSpecularAA) { activeFields.Add("SpecularAA"); } if (masterNode.specularOcclusion.isOn) { // We don't optimize based eg on baked ambient occlusion missing a texture, this makes this baked, data-based // SpecularOcclusion a waste (non baked, SSAO-based SpecularOcclusion is always applied with the TriACE trick), // but the user should know better. // TODOTODO: rename the UI to "baked specular occlusion" and "baked AO" ? activeFields.Add("SpecularOcclusion"); } // // Input special-casing predicates: // if (masterNode.IsSlotConnected(StackLitMasterNode.BentNormalSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.BentNormalSlotId)) { activeFields.Add("BentNormal"); } if (masterNode.IsSlotConnected(StackLitMasterNode.TangentSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.TangentSlotId)) { activeFields.Add("Tangent"); } // The following idiom enables an optimization on feature ports that don't have an enable switch in the settings // view, where the default value might not produce a visual result and incur a processing cost we want to avoid. // For ambient occlusion, this is the case for the SpecularOcclusion calculations which also depend on it, // where a value of 1 will produce no results. // See SpecularOcclusion, we don't optimize out this case... if (pass.PixelShaderUsesSlot(StackLitMasterNode.AmbientOcclusionSlotId)) { bool connected = masterNode.IsSlotConnected(StackLitMasterNode.AmbientOcclusionSlotId); var ambientOcclusionSlot = masterNode.FindSlot <Vector1MaterialSlot>(StackLitMasterNode.AmbientOcclusionSlotId); // master node always has it, assert ambientOcclusionSlot != null if (connected || ambientOcclusionSlot.value != ambientOcclusionSlot.defaultValue) { activeFields.Add("AmbientOcclusion"); } } if (masterNode.IsSlotConnected(StackLitMasterNode.CoatNormalSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.CoatNormalSlotId)) { activeFields.Add("CoatNormal"); } if (masterNode.IsSlotConnected(StackLitMasterNode.LightingSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.LightingSlotId)) { activeFields.Add("LightingGI"); } if (masterNode.IsSlotConnected(StackLitMasterNode.BackLightingSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.BackLightingSlotId)) { activeFields.Add("BackLightingGI"); } return(activeFields); }
private static HashSet <string> GetActiveFieldsFromMasterNode(AbstractMaterialNode iMasterNode, Pass pass) { HashSet <string> activeFields = new HashSet <string>(); FabricMasterNode masterNode = iMasterNode as FabricMasterNode; if (masterNode == null) { return(activeFields); } if (masterNode.doubleSidedMode != DoubleSidedMode.Disabled) { activeFields.Add("DoubleSided"); if (pass.ShaderPassName != "SHADERPASS_MOTION_VECTORS") // HACK to get around lack of a good interpolator dependency system { // we need to be able to build interpolators using multiple input structs // also: should only require isFrontFace if Normals are required... if (masterNode.doubleSidedMode == DoubleSidedMode.FlippedNormals) { activeFields.Add("DoubleSided.Flip"); } else if (masterNode.doubleSidedMode == DoubleSidedMode.MirroredNormals) { activeFields.Add("DoubleSided.Mirror"); } // Important: the following is used in SharedCode.template.hlsl for determining the normal flip mode activeFields.Add("FragInputs.isFrontFace"); } } switch (masterNode.materialType) { case FabricMasterNode.MaterialType.CottonWool: activeFields.Add("Material.CottonWool"); break; case FabricMasterNode.MaterialType.Silk: activeFields.Add("Material.Silk"); break; default: UnityEngine.Debug.LogError("Unknown material type: " + masterNode.materialType); break; } if (masterNode.alphaTest.isOn) { if (pass.PixelShaderUsesSlot(FabricMasterNode.AlphaClipThresholdSlotId)) { activeFields.Add("AlphaTest"); } } if (masterNode.surfaceType != SurfaceType.Opaque) { activeFields.Add("SurfaceType.Transparent"); if (masterNode.alphaMode == AlphaMode.Alpha) { activeFields.Add("BlendMode.Alpha"); } else if (masterNode.alphaMode == AlphaMode.Premultiply) { activeFields.Add("BlendMode.Premultiply"); } else if (masterNode.alphaMode == AlphaMode.Additive) { activeFields.Add("BlendMode.Add"); } if (masterNode.blendPreserveSpecular.isOn) { activeFields.Add("BlendMode.PreserveSpecular"); } if (masterNode.transparencyFog.isOn) { activeFields.Add("AlphaFog"); } } if (!masterNode.receiveDecals.isOn) { activeFields.Add("DisableDecals"); } if (!masterNode.receiveSSR.isOn) { activeFields.Add("DisableSSR"); } if (masterNode.energyConservingSpecular.isOn) { activeFields.Add("Specular.EnergyConserving"); } if (masterNode.transmission.isOn) { activeFields.Add("Material.Transmission"); } if (masterNode.subsurfaceScattering.isOn && masterNode.surfaceType != SurfaceType.Transparent) { activeFields.Add("Material.SubsurfaceScattering"); } if (masterNode.IsSlotConnected(FabricMasterNode.BentNormalSlotId) && pass.PixelShaderUsesSlot(FabricMasterNode.BentNormalSlotId)) { activeFields.Add("BentNormal"); } if (masterNode.IsSlotConnected(FabricMasterNode.TangentSlotId) && pass.PixelShaderUsesSlot(FabricMasterNode.TangentSlotId)) { activeFields.Add("Tangent"); } switch (masterNode.specularOcclusionMode) { case SpecularOcclusionMode.Off: break; case SpecularOcclusionMode.FromAO: activeFields.Add("SpecularOcclusionFromAO"); break; case SpecularOcclusionMode.FromAOAndBentNormal: activeFields.Add("SpecularOcclusionFromAOBentNormal"); break; case SpecularOcclusionMode.Custom: activeFields.Add("SpecularOcclusionCustom"); break; default: break; } if (pass.PixelShaderUsesSlot(FabricMasterNode.AmbientOcclusionSlotId)) { var occlusionSlot = masterNode.FindSlot <Vector1MaterialSlot>(FabricMasterNode.AmbientOcclusionSlotId); bool connected = masterNode.IsSlotConnected(FabricMasterNode.AmbientOcclusionSlotId); if (connected || occlusionSlot.value != occlusionSlot.defaultValue) { activeFields.Add("AmbientOcclusion"); } } if (masterNode.IsSlotConnected(FabricMasterNode.LightingSlotId) && pass.PixelShaderUsesSlot(FabricMasterNode.LightingSlotId)) { activeFields.Add("LightingGI"); } if (masterNode.IsSlotConnected(FabricMasterNode.BackLightingSlotId) && pass.PixelShaderUsesSlot(FabricMasterNode.BackLightingSlotId)) { activeFields.Add("BackLightingGI"); } if (masterNode.depthOffset.isOn && pass.PixelShaderUsesSlot(FabricMasterNode.DepthOffsetSlotId)) { activeFields.Add("DepthOffset"); } return(activeFields); }
private static HashSet <string> GetActiveFieldsFromMasterNode(AbstractMaterialNode iMasterNode, Pass pass) { HashSet <string> activeFields = new HashSet <string>(); HairMasterNode masterNode = iMasterNode as HairMasterNode; if (masterNode == null) { return(activeFields); } if (masterNode.doubleSidedMode != DoubleSidedMode.Disabled) { if (pass.ShaderPassName != "SHADERPASS_MOTION_VECTORS") // HACK to get around lack of a good interpolator dependency system { // we need to be able to build interpolators using multiple input structs // also: should only require isFrontFace if Normals are required... // Important: the following is used in SharedCode.template.hlsl for determining the normal flip mode activeFields.Add("FragInputs.isFrontFace"); } } switch (masterNode.materialType) { case HairMasterNode.MaterialType.KajiyaKay: activeFields.Add("Material.KajiyaKay"); break; default: UnityEngine.Debug.LogError("Unknown material type: " + masterNode.materialType); break; } if (masterNode.alphaTest.isOn) { int count = 0; // If alpha test shadow is enable, we use it, otherwise we use the regular test if (pass.PixelShaderUsesSlot(HairMasterNode.AlphaClipThresholdShadowSlotId) && masterNode.alphaTestShadow.isOn) { activeFields.Add("AlphaTestShadow"); ++count; } else if (pass.PixelShaderUsesSlot(HairMasterNode.AlphaClipThresholdSlotId)) { activeFields.Add("AlphaTest"); ++count; } // Other alpha test are suppose to be alone else if (pass.PixelShaderUsesSlot(HairMasterNode.AlphaClipThresholdDepthPrepassSlotId)) { activeFields.Add("AlphaTestPrepass"); ++count; } else if (pass.PixelShaderUsesSlot(HairMasterNode.AlphaClipThresholdDepthPostpassSlotId)) { activeFields.Add("AlphaTestPostpass"); ++count; } UnityEngine.Debug.Assert(count == 1, "Alpha test value not set correctly"); } if (masterNode.surfaceType != SurfaceType.Opaque) { if (masterNode.transparencyFog.isOn) { activeFields.Add("AlphaFog"); } if (masterNode.transparentWritesMotionVec.isOn) { activeFields.Add("TransparentWritesMotionVec"); } if (masterNode.blendPreserveSpecular.isOn) { activeFields.Add("BlendMode.PreserveSpecular"); } } if (!masterNode.receiveDecals.isOn) { activeFields.Add("DisableDecals"); } if (!masterNode.receiveSSR.isOn) { activeFields.Add("DisableSSR"); } if (masterNode.specularAA.isOn && pass.PixelShaderUsesSlot(HairMasterNode.SpecularAAThresholdSlotId) && pass.PixelShaderUsesSlot(HairMasterNode.SpecularAAScreenSpaceVarianceSlotId)) { activeFields.Add("Specular.AA"); } if (masterNode.IsSlotConnected(HairMasterNode.BentNormalSlotId) && pass.PixelShaderUsesSlot(HairMasterNode.BentNormalSlotId)) { activeFields.Add("BentNormal"); } if (masterNode.IsSlotConnected(HairMasterNode.HairStrandDirectionSlotId) && pass.PixelShaderUsesSlot(HairMasterNode.HairStrandDirectionSlotId)) { activeFields.Add("HairStrandDirection"); } if (masterNode.IsSlotConnected(HairMasterNode.TransmittanceSlotId) && pass.PixelShaderUsesSlot(HairMasterNode.TransmittanceSlotId)) { activeFields.Add(HairMasterNode.TransmittanceSlotName); } if (masterNode.IsSlotConnected(HairMasterNode.RimTransmissionIntensitySlotId) && pass.PixelShaderUsesSlot(HairMasterNode.RimTransmissionIntensitySlotId)) { activeFields.Add(HairMasterNode.RimTransmissionIntensitySlotName); } if (masterNode.useLightFacingNormal.isOn) { activeFields.Add("UseLightFacingNormal"); } switch (masterNode.specularOcclusionMode) { case SpecularOcclusionMode.Off: break; case SpecularOcclusionMode.FromAO: activeFields.Add("SpecularOcclusionFromAO"); break; case SpecularOcclusionMode.FromAOAndBentNormal: activeFields.Add("SpecularOcclusionFromAOBentNormal"); break; case SpecularOcclusionMode.Custom: activeFields.Add("SpecularOcclusionCustom"); break; default: break; } if (pass.PixelShaderUsesSlot(HairMasterNode.AmbientOcclusionSlotId)) { var occlusionSlot = masterNode.FindSlot <Vector1MaterialSlot>(HairMasterNode.AmbientOcclusionSlotId); bool connected = masterNode.IsSlotConnected(HairMasterNode.AmbientOcclusionSlotId); if (connected || occlusionSlot.value != occlusionSlot.defaultValue) { activeFields.Add("AmbientOcclusion"); } } if (masterNode.IsSlotConnected(HairMasterNode.LightingSlotId) && pass.PixelShaderUsesSlot(HairMasterNode.LightingSlotId)) { activeFields.Add("LightingGI"); } if (masterNode.IsSlotConnected(HairMasterNode.BackLightingSlotId) && pass.PixelShaderUsesSlot(HairMasterNode.LightingSlotId)) { activeFields.Add("BackLightingGI"); } if (masterNode.depthOffset.isOn && pass.PixelShaderUsesSlot(HairMasterNode.DepthOffsetSlotId)) { activeFields.Add("DepthOffset"); } return(activeFields); }
private static HashSet <string> GetActiveFieldsFromMasterNode(INode iMasterNode, Pass pass) { HashSet <string> activeFields = new HashSet <string>(); FabricMasterNode masterNode = iMasterNode as FabricMasterNode; if (masterNode == null) { return(activeFields); } if (masterNode.doubleSidedMode != DoubleSidedMode.Disabled) { activeFields.Add("DoubleSided"); if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system { // we need to be able to build interpolators using multiple input structs // also: should only require isFrontFace if Normals are required... if (masterNode.doubleSidedMode == DoubleSidedMode.FlippedNormals) { activeFields.Add("DoubleSided.Flip"); } else if (masterNode.doubleSidedMode == DoubleSidedMode.MirroredNormals) { activeFields.Add("DoubleSided.Mirror"); } activeFields.Add("FragInputs.isFrontFace"); // will need this for determining normal flip mode } } switch (masterNode.materialType) { case FabricMasterNode.MaterialType.CottonWool: activeFields.Add("Material.CottonWool"); break; case FabricMasterNode.MaterialType.Silk: activeFields.Add("Material.Silk"); break; default: UnityEngine.Debug.LogError("Unknown material type: " + masterNode.materialType); break; } if (masterNode.alphaTest.isOn) { int count = 0; if (pass.PixelShaderUsesSlot(FabricMasterNode.AlphaThresholdSlotId)) { activeFields.Add("AlphaTest"); ++count; } if (pass.PixelShaderUsesSlot(FabricMasterNode.AlphaThresholdDepthPrepassSlotId)) { activeFields.Add("AlphaTestPrepass"); ++count; } if (pass.PixelShaderUsesSlot(FabricMasterNode.AlphaThresholdDepthPostpassSlotId)) { activeFields.Add("AlphaTestPostpass"); ++count; } UnityEngine.Debug.Assert(count == 1, "Alpha test value not set correctly"); } if (masterNode.surfaceType != SurfaceType.Opaque) { activeFields.Add("SurfaceType.Transparent"); if (masterNode.alphaMode == AlphaMode.Alpha) { activeFields.Add("BlendMode.Alpha"); } else if (masterNode.alphaMode == AlphaMode.Premultiply) { activeFields.Add("BlendMode.Premultiply"); } else if (masterNode.alphaMode == AlphaMode.Additive) { activeFields.Add("BlendMode.Add"); } if (masterNode.blendPreserveSpecular.isOn) { activeFields.Add("BlendMode.PreserveSpecular"); } if (masterNode.transparencyFog.isOn) { activeFields.Add("AlphaFog"); } } if (masterNode.receiveDecals.isOn) { activeFields.Add("Decals"); } if (!masterNode.receiveSSR.isOn) { activeFields.Add("DisableSSR"); } if (masterNode.energyConservingSpecular.isOn) { activeFields.Add("Specular.EnergyConserving"); } if (masterNode.transmission.isOn) { activeFields.Add("SurfaceDescription.Transmission"); } if (masterNode.subsurfaceScattering.isOn) { activeFields.Add("SurfaceDescription.SubsurfaceScattering"); } if (masterNode.IsSlotConnected(FabricMasterNode.TangentSlotId) && pass.PixelShaderUsesSlot(FabricMasterNode.TangentSlotId)) { activeFields.Add("Tangent"); } switch (masterNode.specularOcclusionMode) { case SpecularOcclusionMode.Off: break; case SpecularOcclusionMode.FromAO: activeFields.Add("SpecularOcclusionFromAO"); break; case SpecularOcclusionMode.FromAOAndBentNormal: activeFields.Add("SpecularOcclusionFromAOBentNormal"); break; case SpecularOcclusionMode.Custom: activeFields.Add("SpecularOcclusionCustom"); break; default: break; } if (pass.PixelShaderUsesSlot(FabricMasterNode.AmbientOcclusionSlotId)) { var occlusionSlot = masterNode.FindSlot <Vector1MaterialSlot>(FabricMasterNode.AmbientOcclusionSlotId); if (occlusionSlot.value != occlusionSlot.defaultValue) { activeFields.Add("Occlusion"); } } return(activeFields); }
private static HashSet <string> GetActiveFieldsFromMasterNode(INode iMasterNode, Pass pass) { HashSet <string> activeFields = new HashSet <string>(); HDLitMasterNode masterNode = iMasterNode as HDLitMasterNode; if (masterNode == null) { return(activeFields); } if (masterNode.doubleSidedMode != DoubleSidedMode.Disabled) { activeFields.Add("DoubleSided"); if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system { // we need to be able to build interpolators using multiple input structs // also: should only require isFrontFace if Normals are required... if (masterNode.doubleSidedMode == DoubleSidedMode.FlippedNormals) { activeFields.Add("DoubleSided.Flip"); } else if (masterNode.doubleSidedMode == DoubleSidedMode.MirroredNormals) { activeFields.Add("DoubleSided.Mirror"); } activeFields.Add("FragInputs.isFrontFace"); // will need this for determining normal flip mode } } switch (masterNode.materialType) { case HDLitMasterNode.MaterialType.Anisotropy: activeFields.Add("Material.Anisotropy"); break; case HDLitMasterNode.MaterialType.Iridescence: activeFields.Add("Material.Iridescence"); break; case HDLitMasterNode.MaterialType.SpecularColor: activeFields.Add("Material.SpecularColor"); break; case HDLitMasterNode.MaterialType.Standard: activeFields.Add("Material.Standard"); break; case HDLitMasterNode.MaterialType.SubsurfaceScattering: { activeFields.Add("Material.SubsurfaceScattering"); if (masterNode.sssTransmission.isOn) { activeFields.Add("Material.Transmission"); } } break; case HDLitMasterNode.MaterialType.Translucent: { activeFields.Add("Material.Translucent"); activeFields.Add("Material.Transmission"); } break; default: UnityEngine.Debug.LogError("Unknown material type: " + masterNode.materialType); break; } if (masterNode.alphaTest.isOn) { int count = 0; if (pass.PixelShaderUsesSlot(HDLitMasterNode.AlphaThresholdSlotId)) { activeFields.Add("AlphaTest"); ++count; } if (pass.PixelShaderUsesSlot(HDLitMasterNode.AlphaThresholdDepthPrepassSlotId)) { activeFields.Add("AlphaTestPrepass"); ++count; } if (pass.PixelShaderUsesSlot(HDLitMasterNode.AlphaThresholdDepthPostpassSlotId)) { activeFields.Add("AlphaTestPostpass"); ++count; } UnityEngine.Debug.Assert(count == 1, "Alpha test value not set correctly"); } if (masterNode.surfaceType != SurfaceType.Opaque) { activeFields.Add("SurfaceType.Transparent"); if (masterNode.alphaMode == AlphaMode.Alpha) { activeFields.Add("BlendMode.Alpha"); } else if (masterNode.alphaMode == AlphaMode.Premultiply) { activeFields.Add("BlendMode.Premultiply"); } else if (masterNode.alphaMode == AlphaMode.Additive) { activeFields.Add("BlendMode.Add"); } if (masterNode.blendPreserveSpecular.isOn) { activeFields.Add("BlendMode.PreserveSpecular"); } if (masterNode.transparencyFog.isOn) { activeFields.Add("AlphaFog"); } } if (masterNode.receiveDecals.isOn) { activeFields.Add("Decals"); } if (masterNode.specularAA.isOn && pass.PixelShaderUsesSlot(HDLitMasterNode.SpecularAAThresholdSlotId) && pass.PixelShaderUsesSlot(HDLitMasterNode.SpecularAAScreenSpaceVarianceSlotId)) { activeFields.Add("Specular.AA"); } if (masterNode.energyConservingSpecular.isOn) { activeFields.Add("Specular.EnergyConserving"); } if (masterNode.HasRefraction()) { activeFields.Add("Refraction"); switch (masterNode.refractionModel) { case ScreenSpaceLighting.RefractionModel.Plane: activeFields.Add("RefractionPlane"); break; case ScreenSpaceLighting.RefractionModel.Sphere: activeFields.Add("RefractionSphere"); break; default: UnityEngine.Debug.LogError("Unknown refraction model: " + masterNode.refractionModel); break; } switch (masterNode.projectionModel) { case HDLitMasterNode.ProjectionModelLit.Proxy: activeFields.Add("RefractionSSRayProxy"); break; case HDLitMasterNode.ProjectionModelLit.HiZ: activeFields.Add("RefractionSSRayHiZ"); break; default: UnityEngine.Debug.LogError("Unknown projection model: " + masterNode.projectionModel); break; } } if (masterNode.IsSlotConnected(HDLitMasterNode.BentNormalSlotId) && pass.PixelShaderUsesSlot(HDLitMasterNode.BentNormalSlotId)) { activeFields.Add("BentNormal"); } if (masterNode.IsSlotConnected(HDLitMasterNode.TangentSlotId) && pass.PixelShaderUsesSlot(HDLitMasterNode.TangentSlotId)) { activeFields.Add("Tangent"); } switch (masterNode.specularOcclusionMode) { case SpecularOcclusionMode.Off: break; case SpecularOcclusionMode.On: activeFields.Add("SpecularOcclusion"); break; case SpecularOcclusionMode.OnUseBentNormal: activeFields.Add("BentNormalSpecularOcclusion"); break; default: break; } if (pass.PixelShaderUsesSlot(HDLitMasterNode.AmbientOcclusionSlotId)) { var occlusionSlot = masterNode.FindSlot <Vector1MaterialSlot>(HDLitMasterNode.AmbientOcclusionSlotId); if (occlusionSlot.value != occlusionSlot.defaultValue) { activeFields.Add("Occlusion"); } } return(activeFields); }