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
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();
|
|
}
|
|
}
|