private static bool GenerateShaderPassLit(StackLitMasterNode masterNode, Pass pass, GenerationMode mode, ShaderGenerator result, List <string> sourceAssetDependencyPaths) { if (mode == GenerationMode.ForReals || pass.UseInPreview) { pass.OnGeneratePass(masterNode); // apply master node options to active fields var activeFields = GetActiveFieldsFromMasterNode(masterNode, pass); // use standard shader pass generation bool vertexActive = masterNode.IsSlotConnected(StackLitMasterNode.PositionSlotId); return(HDSubShaderUtilities.GenerateShaderPass(masterNode, pass, mode, activeFields, result, sourceAssetDependencyPaths, vertexActive)); } else { return(false); } }
private static void AddPixelShaderSlotsForWriteNormalBufferPasses(StackLitMasterNode masterNode, ref Pass pass) { // See StackLit.hlsl:ConvertSurfaceDataToNormalData() // Note: We remove the slots we're adding as the editor will constantly regenerate the shader but // without recreating the nodes thus the passes in the subshader object. if (masterNode.coat.isOn) { // Check ConvertSurfaceDataToNormalData, in this case, we only need those: pass.PixelShaderSlots.Remove(StackLitMasterNode.CoatSmoothnessSlotId); pass.PixelShaderSlots.Add(StackLitMasterNode.CoatSmoothnessSlotId); pass.PixelShaderSlots.Remove(StackLitMasterNode.CoatNormalSlotId); pass.PixelShaderSlots.Add(StackLitMasterNode.CoatNormalSlotId); } else { pass.PixelShaderSlots.Remove(StackLitMasterNode.NormalSlotId); pass.PixelShaderSlots.Add(StackLitMasterNode.NormalSlotId); pass.PixelShaderSlots.Remove(StackLitMasterNode.LobeMixSlotId); pass.PixelShaderSlots.Add(StackLitMasterNode.LobeMixSlotId); pass.PixelShaderSlots.Remove(StackLitMasterNode.SmoothnessASlotId); pass.PixelShaderSlots.Add(StackLitMasterNode.SmoothnessASlotId); pass.PixelShaderSlots.Remove(StackLitMasterNode.SmoothnessBSlotId); pass.PixelShaderSlots.Add(StackLitMasterNode.SmoothnessBSlotId); } // Also, when geometricSpecularAA.isOn, might want to add SpecularAAScreenSpaceVarianceSlotId and SpecularAAThresholdSlotId, // since they affect smoothnesses in surfaceData directly. This is an implicit behavior for Lit, via the GBuffer pass. // Versus performance, might not be important for what it is used for, but SSR uses the roughness too so for now, // add them. if (masterNode.geometricSpecularAA.isOn) // TODOTODO || Normal Map Filtering is on { pass.PixelShaderSlots.Remove(StackLitMasterNode.SpecularAAScreenSpaceVarianceSlotId); pass.PixelShaderSlots.Add(StackLitMasterNode.SpecularAAScreenSpaceVarianceSlotId); pass.PixelShaderSlots.Remove(StackLitMasterNode.SpecularAAThresholdSlotId); pass.PixelShaderSlots.Add(StackLitMasterNode.SpecularAAThresholdSlotId); } }
// // 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 ActiveFields GetActiveFieldsFromMasterNode(AbstractMaterialNode iMasterNode, Pass pass) { var activeFields = new ActiveFields(); var baseActiveFields = activeFields.baseInstance; StackLitMasterNode masterNode = iMasterNode as StackLitMasterNode; 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 baseActiveFields.Add("FragInputs.isFrontFace"); } } if (masterNode.alphaTest.isOn) { if (pass.PixelShaderUsesSlot(StackLitMasterNode.AlphaClipThresholdSlotId)) { baseActiveFields.Add("AlphaTest"); } } if (masterNode.surfaceType != SurfaceType.Opaque) { if (masterNode.transparencyFog.isOn) { baseActiveFields.Add("AlphaFog"); } if (masterNode.blendPreserveSpecular.isOn) { baseActiveFields.Add("BlendMode.PreserveSpecular"); } } // // 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) { baseActiveFields.Add("BaseParametrization.SpecularColor"); } if (masterNode.energyConservingSpecular.isOn) // No defines, suboption of BaseParametrization.SpecularColor { baseActiveFields.Add("EnergyConservingSpecular"); } if (masterNode.anisotropy.isOn) { baseActiveFields.Add("Material.Anisotropy"); } if (masterNode.coat.isOn) { baseActiveFields.Add("Material.Coat"); if (pass.PixelShaderUsesSlot(StackLitMasterNode.CoatMaskSlotId)) { var coatMaskSlot = masterNode.FindSlot <Vector1MaterialSlot>(StackLitMasterNode.CoatMaskSlotId); bool connected = masterNode.IsSlotConnected(StackLitMasterNode.CoatMaskSlotId); if (connected || (coatMaskSlot.value != 0.0f && coatMaskSlot.value != 1.0f)) { baseActiveFields.Add("CoatMask"); } else if (coatMaskSlot.value == 0.0f) { baseActiveFields.Add("CoatMaskZero"); } else if (coatMaskSlot.value == 1.0f) { baseActiveFields.Add("CoatMaskOne"); } } } if (masterNode.coatNormal.isOn) { baseActiveFields.Add("Material.CoatNormal"); } if (masterNode.dualSpecularLobe.isOn) { baseActiveFields.Add("Material.DualSpecularLobe"); if (masterNode.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.HazyGloss) { baseActiveFields.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. baseActiveFields.Add("CapHazinessIfNotMetallic"); } } } } if (masterNode.iridescence.isOn) { baseActiveFields.Add("Material.Iridescence"); } if (masterNode.subsurfaceScattering.isOn && masterNode.surfaceType != SurfaceType.Transparent) { baseActiveFields.Add("Material.SubsurfaceScattering"); } if (masterNode.transmission.isOn) { baseActiveFields.Add("Material.Transmission"); } // Advanced: if (masterNode.anisotropyForAreaLights.isOn) { baseActiveFields.Add("AnisotropyForAreaLights"); } if (masterNode.recomputeStackPerLight.isOn) { baseActiveFields.Add("RecomputeStackPerLight"); } if (masterNode.honorPerLightMinRoughness.isOn) { baseActiveFields.Add("HonorPerLightMinRoughness"); } if (masterNode.shadeBaseUsingRefractedAngles.isOn) { baseActiveFields.Add("ShadeBaseUsingRefractedAngles"); } if (masterNode.debug.isOn) { baseActiveFields.Add("StackLitDebug"); } // // Other property predicates: // if (!masterNode.receiveDecals.isOn) { baseActiveFields.Add("DisableDecals"); } if (!masterNode.receiveSSR.isOn) { baseActiveFields.Add("DisableSSR"); } if (masterNode.addPrecomputedVelocity.isOn) { baseActiveFields.Add("AddPrecomputedVelocity"); } // 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; baseActiveFields.Add("GeometricSpecularAA"); } if (haveSomeSpecularAA) { baseActiveFields.Add("SpecularAA"); } if (masterNode.screenSpaceSpecularOcclusionBaseMode != StackLitMasterNode.SpecularOcclusionBaseMode.Off || masterNode.dataBasedSpecularOcclusionBaseMode != StackLitMasterNode.SpecularOcclusionBaseMode.Off) { // activates main define baseActiveFields.Add("SpecularOcclusion"); } baseActiveFields.Add("ScreenSpaceSpecularOcclusionBaseMode." + masterNode.screenSpaceSpecularOcclusionBaseMode.ToString()); if (StackLitMasterNode.SpecularOcclusionModeUsesVisibilityCone(masterNode.screenSpaceSpecularOcclusionBaseMode)) { baseActiveFields.Add("ScreenSpaceSpecularOcclusionAOConeSize." + masterNode.screenSpaceSpecularOcclusionAOConeSize.ToString()); baseActiveFields.Add("ScreenSpaceSpecularOcclusionAOConeDir." + masterNode.screenSpaceSpecularOcclusionAOConeDir.ToString()); } baseActiveFields.Add("DataBasedSpecularOcclusionBaseMode." + masterNode.dataBasedSpecularOcclusionBaseMode.ToString()); if (StackLitMasterNode.SpecularOcclusionModeUsesVisibilityCone(masterNode.dataBasedSpecularOcclusionBaseMode)) { baseActiveFields.Add("DataBasedSpecularOcclusionAOConeSize." + masterNode.dataBasedSpecularOcclusionAOConeSize.ToString()); } // Set bent normal fixup predicate if needed: if (masterNode.SpecularOcclusionUsesBentNormal()) { baseActiveFields.Add("SpecularOcclusionConeFixupMethod." + masterNode.specularOcclusionConeFixupMethod.ToString()); } // // Input special-casing predicates: // if (masterNode.IsSlotConnected(StackLitMasterNode.BentNormalSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.BentNormalSlotId)) { baseActiveFields.Add("BentNormal"); } if (masterNode.IsSlotConnected(StackLitMasterNode.TangentSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.TangentSlotId)) { baseActiveFields.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) { baseActiveFields.Add("AmbientOcclusion"); } } if (masterNode.IsSlotConnected(StackLitMasterNode.CoatNormalSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.CoatNormalSlotId)) { baseActiveFields.Add("CoatNormal"); } if (masterNode.IsSlotConnected(StackLitMasterNode.LightingSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.LightingSlotId)) { baseActiveFields.Add("LightingGI"); } if (masterNode.IsSlotConnected(StackLitMasterNode.BackLightingSlotId) && pass.PixelShaderUsesSlot(StackLitMasterNode.BackLightingSlotId)) { baseActiveFields.Add("BackLightingGI"); } if (masterNode.depthOffset.isOn && pass.PixelShaderUsesSlot(StackLitMasterNode.DepthOffsetSlotId)) { baseActiveFields.Add("DepthOffset"); } return(activeFields); }
public StackLitSettingsView(StackLitMasterNode node) : base(node) { m_Node = node; PropertySheet ps = new PropertySheet(); int indentLevel = 0; ps.Add(new PropertyRow(CreateLabel("Surface Type", indentLevel)), (row) => { row.Add(new EnumField(SurfaceType.Opaque), (field) => { field.value = m_Node.surfaceType; field.RegisterValueChangedCallback(ChangeSurfaceType); }); }); if (m_Node.surfaceType == SurfaceType.Transparent) { ++indentLevel; // No refraction in StackLit, always show this: ps.Add(new PropertyRow(CreateLabel("Blending Mode", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.AlphaModeLit.Additive), (field) => { field.value = GetAlphaModeLit(m_Node.alphaMode); field.RegisterValueChangedCallback(ChangeBlendMode); }); }); ps.Add(new PropertyRow(CreateLabel("Blend Preserves Specular", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.blendPreserveSpecular.isOn; toggle.OnToggleChanged(ChangeBlendPreserveSpecular); }); }); ps.Add(new PropertyRow(CreateLabel("Fog", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.transparencyFog.isOn; toggle.OnToggleChanged(ChangeTransparencyFog); }); }); ps.Add(new PropertyRow(CreateLabel("Distortion", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.distortion.isOn; toggle.OnToggleChanged(ChangeDistortion); }); }); if (m_Node.distortion.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Distortion Blend Mode", indentLevel)), (row) => { row.Add(new EnumField(DistortionMode.Add), (field) => { field.value = m_Node.distortionMode; field.RegisterValueChangedCallback(ChangeDistortionMode); }); }); ps.Add(new PropertyRow(CreateLabel("Distortion Depth Test", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.distortionDepthTest.isOn; toggle.OnToggleChanged(ChangeDistortionDepthTest); }); }); --indentLevel; } m_SortPiorityField = new IntegerField(); ps.Add(new PropertyRow(CreateLabel("Sort Priority", indentLevel)), (row) => { row.Add(m_SortPiorityField, (field) => { field.value = m_Node.sortPriority; field.RegisterValueChangedCallback(ChangeSortPriority); }); }); ps.Add(new PropertyRow(CreateLabel("Depth Write", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.zWrite.isOn; toggle.OnToggleChanged(ChangeZWrite); }); }); if (m_Node.doubleSidedMode == DoubleSidedMode.Disabled) { ps.Add(new PropertyRow(CreateLabel("Cull Mode", indentLevel)), (row) => { row.Add(new EnumField(m_Node.transparentCullMode), (e) => { e.value = m_Node.transparentCullMode; e.RegisterValueChangedCallback(ChangeTransparentCullMode); }); }); } ps.Add(new PropertyRow(CreateLabel("Depth Test", indentLevel)), (row) => { row.Add(new EnumField(m_Node.zTest), (e) => { e.value = m_Node.zTest; e.RegisterValueChangedCallback(ChangeZTest); }); }); --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Alpha Clipping", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.alphaTest.isOn; toggle.OnToggleChanged(ChangeAlphaTest); }); }); ps.Add(new PropertyRow(CreateLabel("Double-Sided", indentLevel)), (row) => { row.Add(new EnumField(DoubleSidedMode.Disabled), (field) => { field.value = m_Node.doubleSidedMode; field.RegisterValueChangedCallback(ChangeDoubleSidedMode); }); }); ps.Add(new PropertyRow(CreateLabel("Fragment Normal Space", indentLevel)), (row) => { row.Add(new EnumField(NormalDropOffSpace.Tangent), (field) => { field.value = m_Node.normalDropOffSpace; field.RegisterValueChangedCallback(ChangeSpaceOfNormalDropOffMode); }); }); // Rest of UI looks like this: // // baseParametrization // energyConservingSpecular // // anisotropy // coat // coatNormal // dualSpecularLobe // dualSpecularLobeParametrization // capHazinessWrtMetallic // iridescence // subsurfaceScattering // transmission // // receiveDecals // receiveSSR // addPrecomputedVelocity // geometricSpecularAA // specularOcclusion // // anisotropyForAreaLights // recomputeStackPerLight // shadeBaseUsingRefractedAngles // Base parametrization: ps.Add(new PropertyRow(CreateLabel("Base Color Parametrization", indentLevel)), (row) => { row.Add(new EnumField(StackLit.BaseParametrization.BaseMetallic), (field) => { field.value = m_Node.baseParametrization; field.RegisterValueChangedCallback(ChangeBaseParametrization); }); }); if (m_Node.baseParametrization == StackLit.BaseParametrization.SpecularColor) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Energy Conserving Specular", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.energyConservingSpecular.isOn; toggle.OnToggleChanged(ChangeEnergyConservingSpecular); }); }); --indentLevel; } // Material type enables: ps.Add(new PropertyRow(CreateLabel("Material Core Features", indentLevel)), (row) => {}); ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Anisotropy", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.anisotropy.isOn; toggle.OnToggleChanged(ChangeAnisotropy); }); }); ps.Add(new PropertyRow(CreateLabel("Coat", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.coat.isOn; toggle.OnToggleChanged(ChangeCoat); }); }); if (m_Node.coat.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Coat Normal", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.coatNormal.isOn; toggle.OnToggleChanged(ChangeCoatNormal); }); }); --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Dual Specular Lobe", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.dualSpecularLobe.isOn; toggle.OnToggleChanged(ChangeDualSpecularLobe); }); }); if (m_Node.dualSpecularLobe.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Dual SpecularLobe Parametrization", indentLevel)), (row) => { row.Add(new EnumField(StackLit.DualSpecularLobeParametrization.HazyGloss), (field) => { field.value = m_Node.dualSpecularLobeParametrization; field.RegisterValueChangedCallback(ChangeDualSpecularLobeParametrization); }); }); if ((m_Node.baseParametrization == StackLit.BaseParametrization.BaseMetallic) && (m_Node.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.HazyGloss)) { ps.Add(new PropertyRow(CreateLabel("Cap Haziness For Non Metallic", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.capHazinessWrtMetallic.isOn; toggle.OnToggleChanged(ChangeCapHazinessWrtMetallic); }); }); } --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Iridescence", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.iridescence.isOn; toggle.OnToggleChanged(ChangeIridescence); }); }); if (m_Node.surfaceType != SurfaceType.Transparent) { ps.Add(new PropertyRow(CreateLabel("Subsurface Scattering", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.subsurfaceScattering.isOn; toggle.OnToggleChanged(ChangeSubsurfaceScattering); }); }); } ps.Add(new PropertyRow(CreateLabel("Transmission", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.transmission.isOn; toggle.OnToggleChanged(ChangeTransmission); }); }); --indentLevel; // ...Material type enables. ps.Add(new PropertyRow(CreateLabel("Receive Decals", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.receiveDecals.isOn; toggle.OnToggleChanged(ChangeReceiveDecals); }); }); ps.Add(new PropertyRow(CreateLabel("Receive SSR", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.receiveSSR.isOn; toggle.OnToggleChanged(ChangeReceiveSSR); }); }); ps.Add(new PropertyRow(CreateLabel("Add Precomputed Velocity", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.addPrecomputedVelocity.isOn; toggle.OnToggleChanged(ChangeAddPrecomputedVelocity); }); }); ps.Add(new PropertyRow(CreateLabel("Geometric Specular AA", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.geometricSpecularAA.isOn; toggle.OnToggleChanged(ChangeGeometricSpecularAA); }); }); //ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (main enable)", indentLevel)), (row) => //{ // row.Add(new Toggle(), (toggle) => // { // toggle.value = m_Node.specularOcclusion.isOn; // toggle.OnToggleChanged(ChangeSpecularOcclusion); // }); //}); // SpecularOcclusion from SSAO if (m_Node.devMode.isOn) { // Only in dev mode do we show controls for SO fed from SSAO: otherwise, we keep the default which is DirectFromAO ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (from SSAO)", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionBaseMode.DirectFromAO), (field) => { field.value = m_Node.screenSpaceSpecularOcclusionBaseMode; field.RegisterValueChangedCallback(ChangeScreenSpaceSpecularOcclusionBaseMode); }); }); if (StackLitMasterNode.SpecularOcclusionModeUsesVisibilityCone(m_Node.screenSpaceSpecularOcclusionBaseMode)) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (SS) AO Cone Weight", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionAOConeSize.CosWeightedAO), (field) => { field.value = m_Node.screenSpaceSpecularOcclusionAOConeSize; field.RegisterValueChangedCallback(ChangeScreenSpaceSpecularOcclusionAOConeSize); }); }); ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (SS) AO Cone Dir", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionAOConeDir.ShadingNormal), (field) => { field.value = m_Node.screenSpaceSpecularOcclusionAOConeDir; field.RegisterValueChangedCallback(ChangeScreenSpaceSpecularOcclusionAOConeDir); }); }); --indentLevel; } } // SpecularOcclusion from input AO (baked or data-based SO) { ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (from input AO)", indentLevel)), (row) => { if (m_Node.devMode.isOn) { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionBaseMode.DirectFromAO), (field) => { field.value = m_Node.dataBasedSpecularOcclusionBaseMode; field.RegisterValueChangedCallback(ChangeDataBasedSpecularOcclusionBaseMode); }); } else { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionBaseModeSimple.DirectFromAO), (field) => { // In non-dev mode, parse any enum value set to a method not shown in the simple UI as SPTD (highest quality) method: StackLitMasterNode.SpecularOcclusionBaseModeSimple simpleUIEnumValue = Enum.TryParse(m_Node.dataBasedSpecularOcclusionBaseMode.ToString(), out StackLitMasterNode.SpecularOcclusionBaseModeSimple parsedValue) ? parsedValue : StackLitMasterNode.SpecularOcclusionBaseModeSimple.SPTDIntegrationOfBentAO; field.value = simpleUIEnumValue; field.RegisterValueChangedCallback(ChangeDataBasedSpecularOcclusionBaseModeSimpleUI); }); } }); if (StackLitMasterNode.SpecularOcclusionModeUsesVisibilityCone(m_Node.dataBasedSpecularOcclusionBaseMode)) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Specular Occlusion AO Cone Weight", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionAOConeSize.CosWeightedBentCorrectAO), (field) => { field.value = m_Node.dataBasedSpecularOcclusionAOConeSize; field.RegisterValueChangedCallback(ChangeDataBasedSpecularOcclusionAOConeSize); }); }); --indentLevel; } } if (m_Node.SpecularOcclusionUsesBentNormal()) { if (m_Node.devMode.isOn) { ps.Add(new PropertyRow(CreateLabel("Specular Occlusion Bent Cone Fixup", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionConeFixupMethod.Off), (field) => { field.value = m_Node.specularOcclusionConeFixupMethod; field.RegisterValueChangedCallback(ChangeSpecularOcclusionConeFixupMethod); }); }); } else { // Just show a simple toggle when not in dev mode ps.Add(new PropertyRow(CreateLabel("Specular Occlusion Bent Cone Fixup", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.specularOcclusionConeFixupMethod != StackLitMasterNode.SpecularOcclusionConeFixupMethod.Off; toggle.OnToggleChanged(ChangeSpecularOcclusionConeFixupMethodSimpleUI); }); }); } } ps.Add(new PropertyRow(CreateLabel("Support LOD CrossFade", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.supportLodCrossFade.isOn; toggle.OnToggleChanged(ChangeSupportLODCrossFade); }); }); ps.Add(new PropertyRow(CreateLabel("Advanced Options", indentLevel)), (row) => {}); ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Anisotropy For Area Lights", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.anisotropyForAreaLights.isOn; toggle.OnToggleChanged(ChangeAnisotropyForAreaLights); }); }); // Per Punctual/Directional Lights { ps.Add(new PropertyRow(CreateLabel("Per Punctual/Directional Lights:", indentLevel)), (row) => { }); ++indentLevel; if (m_Node.coat.isOn) { ps.Add(new PropertyRow(CreateLabel("Base Layer Uses Refracted Angles", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.shadeBaseUsingRefractedAngles.isOn; toggle.OnToggleChanged(ChangeShadeBaseUsingRefractedAngles); }); }); } if (m_Node.coat.isOn || m_Node.iridescence.isOn) { ps.Add(new PropertyRow(CreateLabel("Recompute Stack & Iridescence", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.recomputeStackPerLight.isOn; toggle.OnToggleChanged(ChangeRecomputeStackPerLight); }); }); } ps.Add(new PropertyRow(CreateLabel("Honor Per Light Max Smoothness", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.honorPerLightMinRoughness.isOn; toggle.OnToggleChanged(ChangeHonorPerLightMinRoughness); }); }); --indentLevel; } // Per Punctual/Directional Lights // Uncomment to show the dev mode UI: // //ps.Add(new PropertyRow(CreateLabel("Enable Dev Mode", indentLevel)), (row) => //{ // row.Add(new Toggle(), (toggle) => // { // toggle.value = m_Node.devMode.isOn; // toggle.OnToggleChanged(ChangeDevMode); // }); //}); if (m_Node.devMode.isOn) { ps.Add(new PropertyRow(CreateLabel("Show And Enable StackLit Debugs", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.debug.isOn; toggle.OnToggleChanged(ChangeDebug); }); }); } ps.Add(new PropertyRow(CreateLabel("Override Baked GI", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.overrideBakedGI.isOn; toggle.OnToggleChanged(ChangeoverrideBakedGI); }); }); ps.Add(new PropertyRow(CreateLabel("Depth Offset", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.depthOffset.isOn; toggle.OnToggleChanged(ChangeDepthOffset); }); }); --indentLevel; //...Advanced options Add(ps); Add(GetShaderGUIOverridePropertySheet()); }
public StackLitSettingsView(StackLitMasterNode node) { m_Node = node; PropertySheet ps = new PropertySheet(); int indentLevel = 0; ps.Add(new PropertyRow(CreateLabel("Surface Type", indentLevel)), (row) => { row.Add(new EnumField(SurfaceType.Opaque), (field) => { field.value = m_Node.surfaceType; field.RegisterValueChangedCallback(ChangeSurfaceType); }); }); if (m_Node.surfaceType == SurfaceType.Transparent) { ++indentLevel; // No refraction in StackLit, always show this: ps.Add(new PropertyRow(CreateLabel("Blending Mode", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.AlphaModeLit.Additive), (field) => { field.value = GetAlphaModeLit(m_Node.alphaMode); field.RegisterValueChangedCallback(ChangeBlendMode); }); }); ps.Add(new PropertyRow(CreateLabel("Blend Preserves Specular", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.blendPreserveSpecular.isOn; toggle.OnToggleChanged(ChangeBlendPreserveSpecular); }); }); ps.Add(new PropertyRow(CreateLabel("Fog", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.transparencyFog.isOn; toggle.OnToggleChanged(ChangeTransparencyFog); }); }); ps.Add(new PropertyRow(CreateLabel("Distortion", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.distortion.isOn; toggle.OnToggleChanged(ChangeDistortion); }); }); if (m_Node.distortion.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Mode", indentLevel)), (row) => { row.Add(new EnumField(DistortionMode.Add), (field) => { field.value = m_Node.distortionMode; field.RegisterValueChangedCallback(ChangeDistortionMode); }); }); ps.Add(new PropertyRow(CreateLabel("Depth Test", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.distortionDepthTest.isOn; toggle.OnToggleChanged(ChangeDistortionDepthTest); }); }); --indentLevel; } m_SortPiorityField = new IntegerField(); ps.Add(new PropertyRow(CreateLabel("Sort Priority", indentLevel)), (row) => { row.Add(m_SortPiorityField, (field) => { field.value = m_Node.sortPriority; field.RegisterValueChangedCallback(ChangeSortPriority); }); }); ps.Add(new PropertyRow(CreateLabel("ZWrite", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.zWrite.isOn; toggle.OnToggleChanged(ChangeZWrite); }); }); if (m_Node.doubleSidedMode == DoubleSidedMode.Disabled) { ps.Add(new PropertyRow(CreateLabel("Cull Mode", indentLevel)), (row) => { row.Add(new EnumField(m_Node.transparentCullMode), (e) => { e.value = m_Node.transparentCullMode; e.RegisterValueChangedCallback(ChangeTransparentCullMode); }); }); } ps.Add(new PropertyRow(CreateLabel("Z Test", indentLevel)), (row) => { row.Add(new EnumField(m_Node.zTest), (e) => { e.value = m_Node.zTest; e.RegisterValueChangedCallback(ChangeZTest); }); }); --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Alpha Clipping", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.alphaTest.isOn; toggle.OnToggleChanged(ChangeAlphaTest); }); }); ps.Add(new PropertyRow(CreateLabel("Double-Sided", indentLevel)), (row) => { row.Add(new EnumField(DoubleSidedMode.Disabled), (field) => { field.value = m_Node.doubleSidedMode; field.RegisterValueChangedCallback(ChangeDoubleSidedMode); }); }); // Rest of UI looks like this: // // baseParametrization // energyConservingSpecular // // anisotropy // coat // coatNormal // dualSpecularLobe // dualSpecularLobeParametrization // capHazinessWrtMetallic // iridescence // subsurfaceScattering // transmission // // receiveDecals // receiveSSR // addPrecomputedVelocity // geometricSpecularAA // specularOcclusion // // anisotropyForAreaLights // recomputeStackPerLight // shadeBaseUsingRefractedAngles // Base parametrization: ps.Add(new PropertyRow(CreateLabel("Base Color Parametrization", indentLevel)), (row) => { row.Add(new EnumField(StackLit.BaseParametrization.BaseMetallic), (field) => { field.value = m_Node.baseParametrization; field.RegisterValueChangedCallback(ChangeBaseParametrization); }); }); if (m_Node.baseParametrization == StackLit.BaseParametrization.SpecularColor) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Energy Conserving Specular", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.energyConservingSpecular.isOn; toggle.OnToggleChanged(ChangeEnergyConservingSpecular); }); }); --indentLevel; } // Material type enables: ps.Add(new PropertyRow(CreateLabel("Material Core Features", indentLevel)), (row) => {}); ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Anisotropy", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.anisotropy.isOn; toggle.OnToggleChanged(ChangeAnisotropy); }); }); ps.Add(new PropertyRow(CreateLabel("Coat", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.coat.isOn; toggle.OnToggleChanged(ChangeCoat); }); }); if (m_Node.coat.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Coat Normal", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.coatNormal.isOn; toggle.OnToggleChanged(ChangeCoatNormal); }); }); --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Dual Specular Lobe", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.dualSpecularLobe.isOn; toggle.OnToggleChanged(ChangeDualSpecularLobe); }); }); if (m_Node.dualSpecularLobe.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Dual SpecularLobe Parametrization", indentLevel)), (row) => { row.Add(new EnumField(StackLit.DualSpecularLobeParametrization.HazyGloss), (field) => { field.value = m_Node.dualSpecularLobeParametrization; field.RegisterValueChangedCallback(ChangeDualSpecularLobeParametrization); }); }); if ((m_Node.baseParametrization == StackLit.BaseParametrization.BaseMetallic) && (m_Node.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.HazyGloss)) { ps.Add(new PropertyRow(CreateLabel("Cap Haziness For Non Metallic", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.capHazinessWrtMetallic.isOn; toggle.OnToggleChanged(ChangeCapHazinessWrtMetallic); }); }); } --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Iridescence", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.iridescence.isOn; toggle.OnToggleChanged(ChangeIridescence); }); }); if (m_Node.surfaceType != SurfaceType.Transparent) { ps.Add(new PropertyRow(CreateLabel("Subsurface Scattering", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.subsurfaceScattering.isOn; toggle.OnToggleChanged(ChangeSubsurfaceScattering); }); }); } ps.Add(new PropertyRow(CreateLabel("Transmission", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.transmission.isOn; toggle.OnToggleChanged(ChangeTransmission); }); }); --indentLevel; // ...Material type enables. ps.Add(new PropertyRow(CreateLabel("Receive Decals", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.receiveDecals.isOn; toggle.OnToggleChanged(ChangeReceiveDecals); }); }); ps.Add(new PropertyRow(CreateLabel("Receive SSR", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.receiveSSR.isOn; toggle.OnToggleChanged(ChangeReceiveSSR); }); }); ps.Add(new PropertyRow(CreateLabel("Add Precomputed Velocity", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.addPrecomputedVelocity.isOn; toggle.OnToggleChanged(ChangeAddPrecomputedVelocity); }); }); ps.Add(new PropertyRow(CreateLabel("Geometric Specular AA", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.geometricSpecularAA.isOn; toggle.OnToggleChanged(ChangeGeometricSpecularAA); }); }); //ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (main enable)", indentLevel)), (row) => //{ // row.Add(new Toggle(), (toggle) => // { // toggle.value = m_Node.specularOcclusion.isOn; // toggle.OnToggleChanged(ChangeSpecularOcclusion); // }); //}); ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (from SSAO)", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionBaseMode.DirectFromAO), (field) => { field.value = m_Node.screenSpaceSpecularOcclusionBaseMode; field.RegisterValueChangedCallback(ChangeScreenSpaceSpecularOcclusionBaseMode); }); }); if (StackLitMasterNode.SpecularOcclusionModeUsesVisibilityCone(m_Node.screenSpaceSpecularOcclusionBaseMode)) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (SS) AO Cone Weight", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionAOConeSize.CosWeightedAO), (field) => { field.value = m_Node.screenSpaceSpecularOcclusionAOConeSize; field.RegisterValueChangedCallback(ChangeScreenSpaceSpecularOcclusionAOConeSize); }); }); ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (SS) AO Cone Dir", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionAOConeDir.ShadingNormal), (field) => { field.value = m_Node.screenSpaceSpecularOcclusionAOConeDir; field.RegisterValueChangedCallback(ChangeScreenSpaceSpecularOcclusionAOConeDir); }); }); --indentLevel; } // TODO: we would ideally need one value per lobe //ps.Add(new PropertyRow(CreateLabel("Specular Occlusion Custom Input", indentLevel)), (row) => //{ // row.Add(new Toggle(), (toggle) => // { // toggle.value = m_Node.specularOcclusionIsCustom.isOn; // toggle.OnToggleChanged(ChangeSpecularOcclusionIsCustom); // }); //}); //if (!m_Node.specularOcclusionIsCustom.isOn) { ps.Add(new PropertyRow(CreateLabel("Specular Occlusion (from input AO)", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionBaseMode.DirectFromAO), (field) => { field.value = m_Node.dataBasedSpecularOcclusionBaseMode; field.RegisterValueChangedCallback(ChangeDataBasedSpecularOcclusionBaseMode); }); }); if (StackLitMasterNode.SpecularOcclusionModeUsesVisibilityCone(m_Node.dataBasedSpecularOcclusionBaseMode)) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Specular Occlusion AO Cone Weight", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionAOConeSize.CosWeightedBentCorrectAO), (field) => { field.value = m_Node.dataBasedSpecularOcclusionAOConeSize; field.RegisterValueChangedCallback(ChangeDataBasedSpecularOcclusionAOConeSize); }); }); --indentLevel; } } if (m_Node.SpecularOcclusionUsesBentNormal()) { ps.Add(new PropertyRow(CreateLabel("Specular Occlusion Bent Cone Fixup", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.SpecularOcclusionConeFixupMethod.Off), (field) => { field.value = m_Node.specularOcclusionConeFixupMethod; field.RegisterValueChangedCallback(ChangeSpecularOcclusionConeFixupMethod); }); }); } ps.Add(new PropertyRow(CreateLabel("Advanced Options", indentLevel)), (row) => {}); ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Anisotropy For Area Lights", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.anisotropyForAreaLights.isOn; toggle.OnToggleChanged(ChangeAnisotropyForAreaLights); }); }); if (m_Node.coat.isOn || m_Node.iridescence.isOn) { ps.Add(new PropertyRow(CreateLabel("Per Punctual/Directional Lights:", indentLevel)), (row) => { }); ++indentLevel; } if (m_Node.coat.isOn) { ps.Add(new PropertyRow(CreateLabel("Base Layer Uses Refracted Angles", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.shadeBaseUsingRefractedAngles.isOn; toggle.OnToggleChanged(ChangeShadeBaseUsingRefractedAngles); }); }); } if (m_Node.coat.isOn || m_Node.iridescence.isOn) { ps.Add(new PropertyRow(CreateLabel("Recompute Stack & Iridescence", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.recomputeStackPerLight.isOn; toggle.OnToggleChanged(ChangeRecomputeStackPerLight); }); }); } if (m_Node.coat.isOn || m_Node.iridescence.isOn) { --indentLevel; // Per Punctual/Directional Lights: } ps.Add(new PropertyRow(CreateLabel("Show And Enable StackLit Debugs", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.debug.isOn; toggle.OnToggleChanged(ChangeDebug); }); }); ps.Add(new PropertyRow(CreateLabel("Override Baked GI", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.overrideBakedGI.isOn; toggle.OnToggleChanged(ChangeoverrideBakedGI); }); }); ps.Add(new PropertyRow(CreateLabel("Depth Offset", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.depthOffset.isOn; toggle.OnToggleChanged(ChangeDepthOffset); }); }); --indentLevel; //...Advanced options Add(ps); }
public StackLitSettingsView(StackLitMasterNode node) { m_Node = node; PropertySheet ps = new PropertySheet(); int indentLevel = 0; ps.Add(new PropertyRow(CreateLabel("Surface Type", indentLevel)), (row) => { row.Add(new EnumField(SurfaceType.Opaque), (field) => { field.value = m_Node.surfaceType; field.OnValueChanged(ChangeSurfaceType); }); }); if (m_Node.surfaceType == SurfaceType.Transparent) { ++indentLevel; // No refraction in StackLit, always show this: ps.Add(new PropertyRow(CreateLabel("Blending Mode", indentLevel)), (row) => { row.Add(new EnumField(StackLitMasterNode.AlphaModeLit.Additive), (field) => { field.value = GetAlphaModeLit(m_Node.alphaMode); field.OnValueChanged(ChangeBlendMode); }); }); ps.Add(new PropertyRow(CreateLabel("Blend Preserves Specular", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.blendPreserveSpecular.isOn; toggle.OnToggleChanged(ChangeBlendPreserveSpecular); }); }); ps.Add(new PropertyRow(CreateLabel("Fog", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.transparencyFog.isOn; toggle.OnToggleChanged(ChangeTransparencyFog); }); }); ps.Add(new PropertyRow(CreateLabel("Distortion", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.distortion.isOn; toggle.OnToggleChanged(ChangeDistortion); }); }); if (m_Node.distortion.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Mode", indentLevel)), (row) => { row.Add(new EnumField(DistortionMode.Add), (field) => { field.value = m_Node.distortionMode; field.OnValueChanged(ChangeDistortionMode); }); }); ps.Add(new PropertyRow(CreateLabel("Depth Test", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.distortionDepthTest.isOn; toggle.OnToggleChanged(ChangeDistortionDepthTest); }); }); --indentLevel; } m_SortPiorityField = new IntegerField(); ps.Add(new PropertyRow(CreateLabel("Sort Priority", indentLevel)), (row) => { row.Add(m_SortPiorityField, (field) => { field.value = m_Node.sortPriority; field.OnValueChanged(ChangeSortPriority); }); }); --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Alpha Cutoff", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.alphaTest.isOn; toggle.OnToggleChanged(ChangeAlphaTest); }); }); ps.Add(new PropertyRow(CreateLabel("Double Sided", indentLevel)), (row) => { row.Add(new EnumField(DoubleSidedMode.Disabled), (field) => { field.value = m_Node.doubleSidedMode; field.OnValueChanged(ChangeDoubleSidedMode); }); }); // Rest of UI looks like this: // // baseParametrization // energyConservingSpecular // // anisotropy // coat // coatNormal // dualSpecularLobe // dualSpecularLobeParametrization // capHazinessWrtMetallic // iridescence // subsurfaceScattering // transmission // // receiveDecals // receiveSSR // geometricSpecularAA // specularOcclusion // // anisotropyForAreaLights // recomputeStackPerLight // shadeBaseUsingRefractedAngles // Base parametrization: ps.Add(new PropertyRow(CreateLabel("Base Color Parametrization", indentLevel)), (row) => { row.Add(new EnumField(StackLit.BaseParametrization.BaseMetallic), (field) => { field.value = m_Node.baseParametrization; field.OnValueChanged(ChangeBaseParametrization); }); }); if (m_Node.baseParametrization == StackLit.BaseParametrization.SpecularColor) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Energy Conserving Specular", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.energyConservingSpecular.isOn; toggle.OnToggleChanged(ChangeEnergyConservingSpecular); }); }); --indentLevel; } // Material type enables: ps.Add(new PropertyRow(CreateLabel("Material Core Features", indentLevel)), (row) => {}); ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Anisotropy", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.anisotropy.isOn; toggle.OnToggleChanged(ChangeAnisotropy); }); }); ps.Add(new PropertyRow(CreateLabel("Coat", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.coat.isOn; toggle.OnToggleChanged(ChangeCoat); }); }); if (m_Node.coat.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Coat Normal", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.coatNormal.isOn; toggle.OnToggleChanged(ChangeCoatNormal); }); }); --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Dual Specular Lobe", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.dualSpecularLobe.isOn; toggle.OnToggleChanged(ChangeDualSpecularLobe); }); }); if (m_Node.dualSpecularLobe.isOn) { ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Dual SpecularLobe Parametrization", indentLevel)), (row) => { row.Add(new EnumField(StackLit.DualSpecularLobeParametrization.HazyGloss), (field) => { field.value = m_Node.dualSpecularLobeParametrization; field.OnValueChanged(ChangeDualSpecularLobeParametrization); }); }); if ((m_Node.baseParametrization == StackLit.BaseParametrization.BaseMetallic) && (m_Node.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.HazyGloss)) { ps.Add(new PropertyRow(CreateLabel("Cap Haziness For Non Metallic", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.capHazinessWrtMetallic.isOn; toggle.OnToggleChanged(ChangeCapHazinessWrtMetallic); }); }); } --indentLevel; } ps.Add(new PropertyRow(CreateLabel("Iridescence", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.iridescence.isOn; toggle.OnToggleChanged(ChangeIridescence); }); }); if (m_Node.surfaceType != SurfaceType.Transparent) { ps.Add(new PropertyRow(CreateLabel("Subsurface Scattering", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.subsurfaceScattering.isOn; toggle.OnToggleChanged(ChangeSubsurfaceScattering); }); }); } ps.Add(new PropertyRow(CreateLabel("Transmission", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.transmission.isOn; toggle.OnToggleChanged(ChangeTransmission); }); }); --indentLevel; // ...Material type enables. ps.Add(new PropertyRow(CreateLabel("Receive Decals", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.receiveDecals.isOn; toggle.OnToggleChanged(ChangeReceiveDecals); }); }); ps.Add(new PropertyRow(CreateLabel("Receive SSR", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.receiveSSR.isOn; toggle.OnToggleChanged(ChangeReceiveSSR); }); }); ps.Add(new PropertyRow(CreateLabel("Specular AA (for geometry)", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.geometricSpecularAA.isOn; toggle.OnToggleChanged(ChangeGeometricSpecularAA); }); }); ps.Add(new PropertyRow(CreateLabel("Specular Occlusion", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.specularOcclusion.isOn; toggle.OnToggleChanged(ChangeSpecularOcclusion); }); }); ps.Add(new PropertyRow(CreateLabel("Advanced Options", indentLevel)), (row) => {}); ++indentLevel; ps.Add(new PropertyRow(CreateLabel("Anisotropy For Area Lights", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.anisotropyForAreaLights.isOn; toggle.OnToggleChanged(ChangeAnisotropyForAreaLights); }); }); if (m_Node.coat.isOn || m_Node.iridescence.isOn) { ps.Add(new PropertyRow(CreateLabel("Per Punctual/Directional Lights:", indentLevel)), (row) => { }); ++indentLevel; } if (m_Node.coat.isOn) { ps.Add(new PropertyRow(CreateLabel("Base Layer Uses Refracted Angles", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.shadeBaseUsingRefractedAngles.isOn; toggle.OnToggleChanged(ChangeShadeBaseUsingRefractedAngles); }); }); } if (m_Node.coat.isOn || m_Node.iridescence.isOn) { ps.Add(new PropertyRow(CreateLabel("Recompute Stack & Iridescence", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.recomputeStackPerLight.isOn; toggle.OnToggleChanged(ChangeRecomputeStackPerLight); }); }); } if (m_Node.coat.isOn || m_Node.iridescence.isOn) { --indentLevel; // Per Punctual/Directional Lights: } ps.Add(new PropertyRow(CreateLabel("Show And Enable StackLit Debugs", indentLevel)), (row) => { row.Add(new Toggle(), (toggle) => { toggle.value = m_Node.debug.isOn; toggle.OnToggleChanged(ChangeDebug); }); }); --indentLevel; //...Advanced options Add(ps); }