You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

425 lines
34 KiB

using System;
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Internal;
using UnityEditor.ShaderGraph.Legacy;
using static UnityEngine.Rendering.HighDefinition.HDMaterial;
using static UnityEditor.Rendering.HighDefinition.HDFields;
namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
{
//TODO:
// clamp in shader code the ranged() properties
// or let inputs (eg mask?) follow invalid values ? Lit does that (let them free running).
sealed partial class StackLitSubTarget : LightingSubTarget, ILegacyTarget, IRequiresData<StackLitData>
{
public StackLitSubTarget() => displayName = "StackLit";
static readonly GUID kSubTargetSourceCodeGuid = new GUID("5f7ba34a143e67647b202a662748dae3"); // StackLitSubTarget.cs
static string[] passTemplateMaterialDirectories = new string[]
{
$"{HDUtils.GetHDRenderPipelinePath()}Editor/Material/StackLit/ShaderGraph/"
};
protected override string[] templateMaterialDirectories => passTemplateMaterialDirectories;
protected override GUID subTargetAssetGuid => kSubTargetSourceCodeGuid;
protected override ShaderID shaderID => ShaderID.SG_StackLit;
protected override FieldDescriptor subShaderField => new FieldDescriptor(kSubShader, "StackLit SubShader", "");
protected override string raytracingInclude => CoreIncludes.kStackLitRaytracing;
protected override string pathtracingInclude => CoreIncludes.kStackLitPathtracing;
protected override string subShaderInclude => CoreIncludes.kStackLit;
// SubShader features
protected override bool supportPathtracing => !TargetsVFX();
protected override bool supportDistortion => true;
protected override bool requireSplitLighting => stackLitData.subsurfaceScattering;
StackLitData m_StackLitData;
StackLitData IRequiresData<StackLitData>.data
{
get => m_StackLitData;
set => m_StackLitData = value;
}
public StackLitData stackLitData
{
get => m_StackLitData;
set => m_StackLitData = value;
}
const string kSSSpecularOcclusionBaseMode = "ScreenSpaceSpecularOcclusionBaseMode";
const string kSSSpecularOcclusionAOConeSize = "ScreenSpaceSpecularOcclusionAOConeSize";
const string kSSSpecularOcclusionAOConeDir = "ScreenSpaceSpecularOcclusionAOConeDir";
const string kDataBasedSpecularOcclusionBaseMode = "DataBasedSpecularOcclusionBaseMode";
const string kDataBasedSpecularOcclusionAOConeSize = "DataBasedSpecularOcclusionAOConeSize";
const string kSpecularOcclusionConeFixupMethod = "SpecularOcclusionConeFixupMethod";
const string kDualSpecularLobeParametrization = "DualSpecularLobeParametrization";
const string kBaseParametrization = "BaseParametrization";
// Material
public static FieldDescriptor Coat = new FieldDescriptor(kMaterial, "Coat", "_MATERIAL_FEATURE_COAT");
public static FieldDescriptor DualSpecularLobe = new FieldDescriptor(kMaterial, "DualSpecularLobe", "_MATERIAL_FEATURE_DUAL_SPECULAR_LOBE");
public static FieldDescriptor CoatNormal = new FieldDescriptor(kMaterial, "CoatNormal", "_MATERIAL_FEATURE_COAT_NORMALMAP");
// Advanced
public static FieldDescriptor AnisotropyForAreaLights = new FieldDescriptor(string.Empty, "AnisotropyForAreaLights", "_ANISOTROPY_FOR_AREA_LIGHTS");
public static FieldDescriptor RecomputeStackPerLight = new FieldDescriptor(string.Empty, "RecomputeStackPerLight", "_VLAYERED_RECOMPUTE_PERLIGHT");
public static FieldDescriptor HonorPerLightMinRoughness = new FieldDescriptor(string.Empty, "HonorPerLightMinRoughness", "_STACK_LIT_HONORS_LIGHT_MIN_ROUGHNESS");
public static FieldDescriptor ShadeBaseUsingRefractedAngles = new FieldDescriptor(string.Empty, "ShadeBaseUsingRefractedAngles", "_VLAYERED_USE_REFRACTED_ANGLES_FOR_BASE");
public static FieldDescriptor StackLitDebug = new FieldDescriptor(string.Empty, "StackLitDebug", "_STACKLIT_DEBUG");
public static FieldDescriptor CapHazinessIfNotMetallic = new FieldDescriptor(string.Empty, "CapHazinessIfNotMetallic", "");
public static FieldDescriptor GeometricSpecularAA = new FieldDescriptor(kSpecular, "GeometricAA", "_ENABLE_GEOMETRIC_SPECULAR_AA 1");
// Screen Space Specular Occlusion Base Mode
public static FieldDescriptor SSSpecularOcclusionBaseModeOff = new FieldDescriptor(kSSSpecularOcclusionBaseMode, "Off", "_SCREENSPACE_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_DISABLED");
public static FieldDescriptor SSSpecularOcclusionBaseModeDirectFromAO = new FieldDescriptor(kSSSpecularOcclusionBaseMode, "DirectFromAO", "_SCREENSPACE_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_FROM_AO");
public static FieldDescriptor SSSpecularOcclusionBaseModeConeConeFromBentAO = new FieldDescriptor(kSSSpecularOcclusionBaseMode, "ConeConeFromBentAO", "_SCREENSPACE_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_CONECONE");
public static FieldDescriptor SSSpecularOcclusionBaseModeSPTDIntegrationOfBentAO = new FieldDescriptor(kSSSpecularOcclusionBaseMode, "SPTDIntegrationOfBentAO", "_SCREENSPACE_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_SPTD");
public static FieldDescriptor SSSpecularOcclusionBaseModeCustom = new FieldDescriptor(kSSSpecularOcclusionBaseMode, "Custom", "_SCREENSPACE_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_FROM_AO");
// Screen Space Specular Occlusion AO Cone Size
public static FieldDescriptor SSSpecularOcclusionAOConeSizeUniformAO = new FieldDescriptor(kSSSpecularOcclusionAOConeSize, "UniformAO", "_SCREENSPACE_SPECULAROCCLUSION_VISIBILITY_FROM_AO_WEIGHT BENT_VISIBILITY_FROM_AO_UNIFORM");
public static FieldDescriptor SSSpecularOcclusionAOConeSizeCosWeightedAO = new FieldDescriptor(kSSSpecularOcclusionAOConeSize, "CosWeightedAO", "_SCREENSPACE_SPECULAROCCLUSION_VISIBILITY_FROM_AO_WEIGHT BENT_VISIBILITY_FROM_AO_COS");
public static FieldDescriptor SSSpecularOcclusionAOConeSizeCosWeightedBentCorrectAO = new FieldDescriptor(kSSSpecularOcclusionAOConeSize, "CosWeightedBentCorrectAO", "_SCREENSPACE_SPECULAROCCLUSION_VISIBILITY_FROM_AO_WEIGHT BENT_VISIBILITY_FROM_AO_COS_BENT_CORRECTION");
// Screen Space Specular Occlusion AO Cone Dir
public static FieldDescriptor SSSpecularOcclusionAOConeDirGeomNormal = new FieldDescriptor(kSSSpecularOcclusionAOConeDir, "GeomNormal", "_SCREENSPACE_SPECULAROCCLUSION_VISIBILITY_DIR BENT_VISIBILITY_DIR_GEOM_NORMAL");
public static FieldDescriptor SSSpecularOcclusionAOConeDirBentNormal = new FieldDescriptor(kSSSpecularOcclusionAOConeDir, "BentNormal", "_SCREENSPACE_SPECULAROCCLUSION_VISIBILITY_DIR BENT_VISIBILITY_DIR_BENT_NORMAL");
public static FieldDescriptor SSSpecularOcclusionAOConeDirShadingNormal = new FieldDescriptor(kSSSpecularOcclusionAOConeDir, "ShadingNormal", "_SCREENSPACE_SPECULAROCCLUSION_VISIBILITY_DIR BENT_VISIBILITY_DIR_SHADING_NORMAL");
// Data Bases Specular Occlusion Base Mode
public static FieldDescriptor DataBasedSpecularOcclusionBaseModeOff = new FieldDescriptor(kDataBasedSpecularOcclusionBaseMode, "Off", "_DATABASED_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_DISABLED");
public static FieldDescriptor DataBasedSpecularOcclusionBaseModeDirectFromAO = new FieldDescriptor(kDataBasedSpecularOcclusionBaseMode, "DirectFromAO", "_DATABASED_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_FROM_AO");
public static FieldDescriptor DataBasedSpecularOcclusionBaseModeConeConeFromBentAO = new FieldDescriptor(kDataBasedSpecularOcclusionBaseMode, "ConeConeFromBentAO", "_DATABASED_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_CONECONE");
public static FieldDescriptor DataBasedSpecularOcclusionBaseModeSPTDIntegrationOfBentAO = new FieldDescriptor(kDataBasedSpecularOcclusionBaseMode, "SPTDIntegrationOfBentAO", "_DATABASED_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_SPTD");
public static FieldDescriptor DataBasedSpecularOcclusionBaseModeCustom = new FieldDescriptor(kDataBasedSpecularOcclusionBaseMode, "Custom", "_DATABASED_SPECULAROCCLUSION_METHOD SPECULAR_OCCLUSION_CUSTOM_EXT_INPUT");
// Data Based Specular Occlusion AO Cone Size
public static FieldDescriptor DataBasedSpecularOcclusionAOConeSizeUniformAO = new FieldDescriptor(kDataBasedSpecularOcclusionAOConeSize, "UniformAO", "_DATABASED_SPECULAROCCLUSION_VISIBILITY_FROM_AO_WEIGHT BENT_VISIBILITY_FROM_AO_UNIFORM");
public static FieldDescriptor DataBasedSpecularOcclusionAOConeSizeCosWeightedAO = new FieldDescriptor(kDataBasedSpecularOcclusionAOConeSize, "CosWeightedAO", "_DATABASED_SPECULAROCCLUSION_VISIBILITY_FROM_AO_WEIGHT BENT_VISIBILITY_FROM_AO_COS");
public static FieldDescriptor DataBasedSpecularOcclusionAOConeSizeCosWeightedBentCorrectAO = new FieldDescriptor(kDataBasedSpecularOcclusionAOConeSize, "CosWeightedBentCorrectAO", "_DATABASED_SPECULAROCCLUSION_VISIBILITY_FROM_AO_WEIGHT BENT_VISIBILITY_FROM_AO_COS_BENT_CORRECTION");
// Specular Occlusion Cone Fixup Method
public static FieldDescriptor SpecularOcclusionConeFixupMethodOff = new FieldDescriptor(kSpecularOcclusionConeFixupMethod, "Off", "_BENT_VISIBILITY_FIXUP_FLAGS BENT_VISIBILITY_FIXUP_FLAGS_NONE");
public static FieldDescriptor SpecularOcclusionConeFixupMethodBoostBSDFRoughness = new FieldDescriptor(kSpecularOcclusionConeFixupMethod, "BoostBSDFRoughness", "_BENT_VISIBILITY_FIXUP_FLAGS BENT_VISIBILITY_FIXUP_FLAGS_BOOST_BSDF_ROUGHNESS");
public static FieldDescriptor SpecularOcclusionConeFixupMethodTiltDirectionToGeomNormal = new FieldDescriptor(kSpecularOcclusionConeFixupMethod, "TiltDirectionToGeomNormal", "_BENT_VISIBILITY_FIXUP_FLAGS BENT_VISIBILITY_FIXUP_FLAGS_TILT_BENTNORMAL_TO_GEOM");
public static FieldDescriptor SpecularOcclusionConeFixupMethodBoostAndTilt = new FieldDescriptor(kSpecularOcclusionConeFixupMethod, "BoostAndTilt", "_BENT_VISIBILITY_FIXUP_FLAGS (BENT_VISIBILITY_FIXUP_FLAGS_BOOST_BSDF_ROUGHNESS|BENT_VISIBILITY_FIXUP_FLAGS_TILT_BENTNORMAL_TO_GEOM)");
// Dual Specular Lobe Parametrization
public static FieldDescriptor HazyGloss = new FieldDescriptor(kDualSpecularLobeParametrization, "HazyGloss", "_MATERIAL_FEATURE_HAZY_GLOSS");
// Base Parametrization
public static FieldDescriptor BaseParamSpecularColor = new FieldDescriptor(kBaseParametrization, "SpecularColor", "_MATERIAL_FEATURE_SPECULAR_COLOR");
protected override SubShaderDescriptor GetRaytracingSubShaderDescriptor()
{
var descriptor = base.GetRaytracingSubShaderDescriptor();
if (stackLitData.subsurfaceScattering)
descriptor.passes.Add(HDShaderPasses.GenerateRaytracingSubsurface());
return descriptor;
}
public override void GetFields(ref TargetFieldContext context)
{
base.GetFields(ref context);
AddDistortionFields(ref context);
var descs = context.blocks.Select(x => x.descriptor);
bool hasDiffusionProfile = (systemData.surfaceType != SurfaceType.Transparent && stackLitData.subsurfaceScattering) || stackLitData.transmission;
// StackLit specific properties
// Material
context.AddField(Anisotropy, stackLitData.anisotropy);
context.AddField(Coat, stackLitData.coat);
context.AddField(CoatMask, stackLitData.coat && context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.CoatMask) &&
descs.Contains(BlockFields.SurfaceDescription.CoatMask));
// context.AddField(CoatMaskZero, coat.isOn && pass.pixelBlocks.Contains(CoatMaskSlotId) &&
// FindSlot<Vector1MaterialSlot>(CoatMaskSlotId).value == 0.0f),
// context.AddField(CoatMaskOne, coat.isOn && pass.pixelBlocks.Contains(CoatMaskSlotId) &&
// FindSlot<Vector1MaterialSlot>(CoatMaskSlotId).value == 1.0f),
context.AddField(CoatNormal, stackLitData.coatNormal
&& (context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.CoatNormalOS)
|| context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.CoatNormalTS)
|| context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.CoatNormalWS)));
context.AddField(Iridescence, stackLitData.iridescence);
context.AddField(SubsurfaceScattering, stackLitData.subsurfaceScattering && systemData.surfaceType != SurfaceType.Transparent);
context.AddField(Transmission, stackLitData.transmission);
context.AddField(DualSpecularLobe, stackLitData.dualSpecularLobe);
// Base Parametrization
// 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:
context.AddField(BaseParamSpecularColor, stackLitData.baseParametrization == StackLit.BaseParametrization.SpecularColor);
// Dual Specular Lobe Parametrization
context.AddField(HazyGloss, stackLitData.dualSpecularLobe &&
stackLitData.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.HazyGloss);
// Misc
context.AddField(EnergyConservingSpecular, stackLitData.energyConservingSpecular && (!hasDiffusionProfile || !stackLitData.useProfileIOR));
// Option for baseParametrization == Metallic && DualSpecularLobeParametrization == HazyGloss:
// Again we assume masternode has HazyGlossMaxDielectricF0 which should always be the case
// if capHazinessWrtMetallic.isOn.
context.AddField(CapHazinessIfNotMetallic, stackLitData.dualSpecularLobe &&
stackLitData.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.HazyGloss &&
stackLitData.capHazinessWrtMetallic && stackLitData.baseParametrization == StackLit.BaseParametrization.BaseMetallic
&& context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.HazyGlossMaxDielectricF0));
// 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)
context.AddField(GeometricSpecularAA, lightingData.specularAA &&
context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.SpecularAAScreenSpaceVariance) &&
context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.SpecularAAThreshold));
context.AddField(SpecularAA, lightingData.specularAA &&
context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.SpecularAAScreenSpaceVariance) &&
context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.SpecularAAThreshold));
context.AddField(SpecularOcclusion, stackLitData.screenSpaceSpecularOcclusionBaseMode != StackLitData.SpecularOcclusionBaseMode.Off ||
stackLitData.dataBasedSpecularOcclusionBaseMode != StackLitData.SpecularOcclusionBaseMode.Off);
context.AddField(UseProfileIor, stackLitData.useProfileIOR && hasDiffusionProfile);
context.AddField(UseProfileLobes, stackLitData.dualSpecularLobeParametrization == StackLit.DualSpecularLobeParametrization.FromDiffusionProfile);
// Advanced
context.AddField(AnisotropyForAreaLights, stackLitData.anisotropyForAreaLights);
context.AddField(RecomputeStackPerLight, stackLitData.recomputeStackPerLight);
context.AddField(HonorPerLightMinRoughness, stackLitData.honorPerLightMinRoughness);
context.AddField(ShadeBaseUsingRefractedAngles, stackLitData.shadeBaseUsingRefractedAngles);
context.AddField(StackLitDebug, stackLitData.debug);
// Screen Space Specular Occlusion Base Mode
context.AddField(SSSpecularOcclusionBaseModeOff, stackLitData.screenSpaceSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.Off);
context.AddField(SSSpecularOcclusionBaseModeDirectFromAO, stackLitData.screenSpaceSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.DirectFromAO);
context.AddField(SSSpecularOcclusionBaseModeConeConeFromBentAO, stackLitData.screenSpaceSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.ConeConeFromBentAO);
context.AddField(SSSpecularOcclusionBaseModeSPTDIntegrationOfBentAO, stackLitData.screenSpaceSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.SPTDIntegrationOfBentAO);
context.AddField(SSSpecularOcclusionBaseModeCustom, stackLitData.screenSpaceSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.Custom);
// Screen Space Specular Occlusion AO Cone Size
context.AddField(SSSpecularOcclusionAOConeSizeUniformAO, SpecularOcclusionModeUsesVisibilityCone(stackLitData.screenSpaceSpecularOcclusionBaseMode) &&
stackLitData.screenSpaceSpecularOcclusionAOConeSize == StackLitData.SpecularOcclusionAOConeSize.UniformAO);
context.AddField(SSSpecularOcclusionAOConeSizeCosWeightedAO, SpecularOcclusionModeUsesVisibilityCone(stackLitData.screenSpaceSpecularOcclusionBaseMode) &&
stackLitData.screenSpaceSpecularOcclusionAOConeSize == StackLitData.SpecularOcclusionAOConeSize.CosWeightedAO);
context.AddField(SSSpecularOcclusionAOConeSizeCosWeightedBentCorrectAO, SpecularOcclusionModeUsesVisibilityCone(stackLitData.screenSpaceSpecularOcclusionBaseMode) &&
stackLitData.screenSpaceSpecularOcclusionAOConeSize == StackLitData.SpecularOcclusionAOConeSize.CosWeightedBentCorrectAO);
// Screen Space Specular Occlusion AO Cone Dir
context.AddField(SSSpecularOcclusionAOConeDirGeomNormal, SpecularOcclusionModeUsesVisibilityCone(stackLitData.screenSpaceSpecularOcclusionBaseMode) &&
stackLitData.screenSpaceSpecularOcclusionAOConeDir == StackLitData.SpecularOcclusionAOConeDir.GeomNormal);
context.AddField(SSSpecularOcclusionAOConeDirBentNormal, SpecularOcclusionModeUsesVisibilityCone(stackLitData.screenSpaceSpecularOcclusionBaseMode) &&
stackLitData.screenSpaceSpecularOcclusionAOConeDir == StackLitData.SpecularOcclusionAOConeDir.BentNormal);
context.AddField(SSSpecularOcclusionAOConeDirShadingNormal, SpecularOcclusionModeUsesVisibilityCone(stackLitData.screenSpaceSpecularOcclusionBaseMode) &&
stackLitData.screenSpaceSpecularOcclusionAOConeDir == StackLitData.SpecularOcclusionAOConeDir.ShadingNormal);
// Data Based Specular Occlusion Base Mode
context.AddField(DataBasedSpecularOcclusionBaseModeOff, stackLitData.dataBasedSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.Off);
context.AddField(DataBasedSpecularOcclusionBaseModeDirectFromAO, stackLitData.dataBasedSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.DirectFromAO);
context.AddField(DataBasedSpecularOcclusionBaseModeConeConeFromBentAO, stackLitData.dataBasedSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.ConeConeFromBentAO);
context.AddField(DataBasedSpecularOcclusionBaseModeSPTDIntegrationOfBentAO, stackLitData.dataBasedSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.SPTDIntegrationOfBentAO);
context.AddField(DataBasedSpecularOcclusionBaseModeCustom, stackLitData.dataBasedSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.Custom);
// Data Based Specular Occlusion AO Cone Size
context.AddField(DataBasedSpecularOcclusionAOConeSizeUniformAO, SpecularOcclusionModeUsesVisibilityCone(stackLitData.dataBasedSpecularOcclusionBaseMode) &&
stackLitData.dataBasedSpecularOcclusionAOConeSize == StackLitData.SpecularOcclusionAOConeSize.UniformAO);
context.AddField(DataBasedSpecularOcclusionAOConeSizeCosWeightedAO, SpecularOcclusionModeUsesVisibilityCone(stackLitData.dataBasedSpecularOcclusionBaseMode) &&
stackLitData.dataBasedSpecularOcclusionAOConeSize == StackLitData.SpecularOcclusionAOConeSize.CosWeightedAO);
context.AddField(DataBasedSpecularOcclusionAOConeSizeCosWeightedBentCorrectAO, SpecularOcclusionModeUsesVisibilityCone(stackLitData.dataBasedSpecularOcclusionBaseMode) &&
stackLitData.dataBasedSpecularOcclusionAOConeSize == StackLitData.SpecularOcclusionAOConeSize.CosWeightedBentCorrectAO);
// Specular Occlusion Cone Fixup Method
context.AddField(SpecularOcclusionConeFixupMethodOff, SpecularOcclusionUsesBentNormal(stackLitData) &&
stackLitData.specularOcclusionConeFixupMethod == StackLitData.SpecularOcclusionConeFixupMethod.Off);
context.AddField(SpecularOcclusionConeFixupMethodBoostBSDFRoughness, SpecularOcclusionUsesBentNormal(stackLitData) &&
stackLitData.specularOcclusionConeFixupMethod == StackLitData.SpecularOcclusionConeFixupMethod.BoostBSDFRoughness);
context.AddField(SpecularOcclusionConeFixupMethodTiltDirectionToGeomNormal, SpecularOcclusionUsesBentNormal(stackLitData) &&
stackLitData.specularOcclusionConeFixupMethod == StackLitData.SpecularOcclusionConeFixupMethod.TiltDirectionToGeomNormal);
context.AddField(SpecularOcclusionConeFixupMethodBoostAndTilt, SpecularOcclusionUsesBentNormal(stackLitData) &&
stackLitData.specularOcclusionConeFixupMethod == StackLitData.SpecularOcclusionConeFixupMethod.BoostAndTilt);
}
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
base.GetActiveBlocks(ref context);
// Common
BlockFieldDescriptor tangentBlock;
switch (lightingData.normalDropOffSpace)
{
case NormalDropOffSpace.Object:
tangentBlock = HDBlockFields.SurfaceDescription.TangentOS;
break;
case NormalDropOffSpace.World:
tangentBlock = HDBlockFields.SurfaceDescription.TangentWS;
break;
default:
tangentBlock = HDBlockFields.SurfaceDescription.TangentTS;
break;
}
context.AddBlock(tangentBlock);
context.AddBlock(HDBlockFields.SurfaceDescription.Anisotropy, stackLitData.anisotropy);
context.AddBlock(HDBlockFields.SurfaceDescription.SubsurfaceMask, stackLitData.subsurfaceScattering);
context.AddBlock(HDBlockFields.SurfaceDescription.TransmissionTint, stackLitData.transmission);
context.AddBlock(HDBlockFields.SurfaceDescription.Thickness, stackLitData.transmission);
context.AddBlock(HDBlockFields.SurfaceDescription.DiffusionProfileHash, stackLitData.subsurfaceScattering || stackLitData.transmission);
// Base Metallic
context.AddBlock(BlockFields.SurfaceDescription.Metallic, stackLitData.baseParametrization == StackLit.BaseParametrization.BaseMetallic);
bool hasDiffusionProfile = (systemData.surfaceType != SurfaceType.Transparent && stackLitData.subsurfaceScattering) || stackLitData.transmission;
if (!(hasDiffusionProfile && stackLitData.useProfileIOR))
{
context.AddBlock(HDBlockFields.SurfaceDescription.DielectricIor, stackLitData.baseParametrization == StackLit.BaseParametrization.BaseMetallic);
context.AddBlock(BlockFields.SurfaceDescription.Specular, stackLitData.baseParametrization == StackLit.BaseParametrization.SpecularColor);
}
// Specular Occlusion
// for custom (external) SO replacing data based SO (which normally comes from some func of DataBasedSOMode(dataAO, optional bent normal))
// TODO: we would ideally need one value per lobe
context.AddBlock(HDBlockFields.SurfaceDescription.SpecularOcclusion, DataBasedSpecularOcclusionIsCustom());
context.AddBlock(HDBlockFields.SurfaceDescription.SOFixupVisibilityRatioThreshold, SpecularOcclusionUsesBentNormal(stackLitData) &&
stackLitData.specularOcclusionConeFixupMethod != StackLitData.SpecularOcclusionConeFixupMethod.Off);
context.AddBlock(HDBlockFields.SurfaceDescription.SOFixupStrengthFactor, SpecularOcclusionUsesBentNormal(stackLitData) &&
stackLitData.specularOcclusionConeFixupMethod != StackLitData.SpecularOcclusionConeFixupMethod.Off);
context.AddBlock(HDBlockFields.SurfaceDescription.SOFixupMaxAddedRoughness, SpecularOcclusionUsesBentNormal(stackLitData) && SpecularOcclusionConeFixupMethodModifiesRoughness(stackLitData.specularOcclusionConeFixupMethod) &&
stackLitData.specularOcclusionConeFixupMethod != StackLitData.SpecularOcclusionConeFixupMethod.Off);
// Coat
context.AddBlock(BlockFields.SurfaceDescription.CoatSmoothness, stackLitData.coat);
context.AddBlock(HDBlockFields.SurfaceDescription.CoatIor, stackLitData.coat);
context.AddBlock(HDBlockFields.SurfaceDescription.CoatThickness, stackLitData.coat);
context.AddBlock(HDBlockFields.SurfaceDescription.CoatExtinction, stackLitData.coat);
context.AddBlock(HDBlockFields.SurfaceDescription.CoatNormalOS, stackLitData.coat && stackLitData.coatNormal && lightingData.normalDropOffSpace == NormalDropOffSpace.Object);
context.AddBlock(HDBlockFields.SurfaceDescription.CoatNormalTS, stackLitData.coat && stackLitData.coatNormal && lightingData.normalDropOffSpace == NormalDropOffSpace.Tangent);
context.AddBlock(HDBlockFields.SurfaceDescription.CoatNormalWS, stackLitData.coat && stackLitData.coatNormal && lightingData.normalDropOffSpace == NormalDropOffSpace.World);
context.AddBlock(BlockFields.SurfaceDescription.CoatMask, stackLitData.coat);
// Dual Specular Lobe
if (stackLitData.dualSpecularLobe)
{
switch (stackLitData.dualSpecularLobeParametrization)
{
case StackLit.DualSpecularLobeParametrization.Direct:
context.AddBlock(HDBlockFields.SurfaceDescription.SmoothnessB);
context.AddBlock(HDBlockFields.SurfaceDescription.LobeMix);
break;
case StackLit.DualSpecularLobeParametrization.HazyGloss:
context.AddBlock(HDBlockFields.SurfaceDescription.Haziness);
context.AddBlock(HDBlockFields.SurfaceDescription.HazeExtent);
context.AddBlock(HDBlockFields.SurfaceDescription.HazyGlossMaxDielectricF0, stackLitData.capHazinessWrtMetallic && stackLitData.baseParametrization == StackLit.BaseParametrization.BaseMetallic);
break;
}
context.AddBlock(HDBlockFields.SurfaceDescription.AnisotropyB, stackLitData.anisotropy);
}
// Iridescence
context.AddBlock(HDBlockFields.SurfaceDescription.IridescenceMask, stackLitData.iridescence);
context.AddBlock(HDBlockFields.SurfaceDescription.IridescenceThickness, stackLitData.iridescence);
context.AddBlock(HDBlockFields.SurfaceDescription.IridescenceCoatFixupTIR, stackLitData.iridescence && stackLitData.coat);
context.AddBlock(HDBlockFields.SurfaceDescription.IridescenceCoatFixupTIRClamp, stackLitData.iridescence && stackLitData.coat);
}
protected override void AddInspectorPropertyBlocks(SubTargetPropertiesGUI blockList)
{
blockList.AddPropertyBlock(new StackLitSurfaceOptionPropertyBlock(SurfaceOptionPropertyBlock.Features.Lit, stackLitData));
if (systemData.surfaceType == SurfaceType.Transparent)
blockList.AddPropertyBlock(new DistortionPropertyBlock());
blockList.AddPropertyBlock(new StackLitAdvancedOptionsPropertyBlock(stackLitData));
}
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
{
base.CollectShaderProperties(collector, generationMode);
if (stackLitData.debug)
{
// We have useful debug options in StackLit, so add them always, and let the UI editor (non shadergraph) handle displaying them
// since this is also the editor that controls the keyword switching for the debug mode.
collector.AddShaderProperty(new Vector4ShaderProperty()
{
overrideReferenceName = "_DebugEnvLobeMask", // xyz is environments lights lobe 0 1 2 Enable, w is Enable VLayering
displayName = "_DebugEnvLobeMask",
value = new Vector4(1.0f, 1.0f, 1.0f, 1.0f)
});
collector.AddShaderProperty(new Vector4ShaderProperty()
{
overrideReferenceName = "_DebugLobeMask", // xyz is analytical dirac lights lobe 0 1 2 Enable", false),
displayName = "_DebugLobeMask",
value = new Vector4(1.0f, 1.0f, 1.0f, 1.0f)
});
collector.AddShaderProperty(new Vector4ShaderProperty()
{
overrideReferenceName = "_DebugAniso", // x is Hack Enable, w is factor
displayName = "_DebugAniso",
value = new Vector4(1.0f, 0.0f, 0.0f, 1000.0f)
});
// _DebugSpecularOcclusion:
//
// eg (2,2,1,2) :
// .x = SO method {0 = fromAO, 1 = conecone, 2 = SPTD},
// .y = bentao algo {0 = uniform, cos, bent cos},
// .z = use upper visible hemisphere clipping,
// .w = The last component of _DebugSpecularOcclusion controls debug visualization:
// -1 colors the object according to the SO algorithm used,
// and values from 1 to 4 controls what the lighting debug display mode will show when set to show "indirect specular occlusion":
// Since there's not one value in our case,
// 0 will show the object all red to indicate to choose one, 1-4 corresponds to showing
// 1 = coat SO, 2 = base lobe A SO, 3 = base lobe B SO, 4 = shows the result of sampling the SSAO texture (screenSpaceAmbientOcclusion).
collector.AddShaderProperty(new Vector4ShaderProperty()
{
overrideReferenceName = "_DebugSpecularOcclusion",
displayName = "_DebugSpecularOcclusion",
value = new Vector4(2.0f, 2.0f, 1.0f, 2.0f)
});
}
}
public static bool SpecularOcclusionModeUsesVisibilityCone(StackLitData.SpecularOcclusionBaseMode soMethod)
{
return (soMethod == StackLitData.SpecularOcclusionBaseMode.ConeConeFromBentAO
|| soMethod == StackLitData.SpecularOcclusionBaseMode.SPTDIntegrationOfBentAO);
}
public static bool SpecularOcclusionUsesBentNormal(StackLitData stackLitData)
{
return (SpecularOcclusionModeUsesVisibilityCone(stackLitData.dataBasedSpecularOcclusionBaseMode)
|| (SpecularOcclusionModeUsesVisibilityCone(stackLitData.screenSpaceSpecularOcclusionBaseMode)
&& stackLitData.screenSpaceSpecularOcclusionAOConeDir == StackLitData.SpecularOcclusionAOConeDir.BentNormal));
}
bool DataBasedSpecularOcclusionIsCustom()
{
return stackLitData.dataBasedSpecularOcclusionBaseMode == StackLitData.SpecularOcclusionBaseMode.Custom;
}
public static bool SpecularOcclusionConeFixupMethodModifiesRoughness(StackLitData.SpecularOcclusionConeFixupMethod soConeFixupMethod)
{
return (soConeFixupMethod == StackLitData.SpecularOcclusionConeFixupMethod.BoostBSDFRoughness
|| soConeFixupMethod == StackLitData.SpecularOcclusionConeFixupMethod.BoostAndTilt);
}
protected override int ComputeMaterialNeedsUpdateHash()
=> base.ComputeMaterialNeedsUpdateHash() * 23 + stackLitData.subsurfaceScattering.GetHashCode();
}
}