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.
 
 
 
 
 

309 lines
15 KiB

using System;
using System.Linq;
using UnityEngine.Rendering.HighDefinition;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Internal;
using UnityEditor.ShaderGraph.Legacy;
using static UnityEngine.Rendering.HighDefinition.HDMaterial;
using static UnityEngine.Rendering.HighDefinition.HDMaterialProperties;
using static UnityEditor.Rendering.HighDefinition.HDFields;
using System.Collections.Generic;
using UnityEditor.Rendering.Fullscreen.ShaderGraph;
using UnityEngine;
namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
{
sealed partial class HDLitSubTarget : LightingSubTarget, ILegacyTarget, IRequiresData<HDLitData>
{
HDLitData m_LitData;
HDLitData IRequiresData<HDLitData>.data
{
get => m_LitData;
set => m_LitData = value;
}
public HDLitData litData
{
get => m_LitData;
set => m_LitData = value;
}
public HDLitSubTarget() => displayName = "Lit";
static readonly GUID kSubTargetSourceCodeGuid = new GUID("caab952c840878340810cca27417971c"); // HDLitSubTarget.cs
static string[] passTemplateMaterialDirectories = new string[]
{
$"{HDUtils.GetHDRenderPipelinePath()}Editor/Material/Lit/ShaderGraph/"
};
protected override string[] templateMaterialDirectories => passTemplateMaterialDirectories;
protected override GUID subTargetAssetGuid => kSubTargetSourceCodeGuid;
protected override string postDecalsInclude => "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitDecalData.hlsl";
protected override ShaderID shaderID => ShaderID.SG_Lit;
protected override string raytracingInclude => CoreIncludes.kLitRaytracing;
protected override string pathtracingInclude => CoreIncludes.kLitPathtracing;
protected override FieldDescriptor subShaderField => new FieldDescriptor(kSubShader, "Lit Subshader", "");
protected override string subShaderInclude => CoreIncludes.kLit;
protected override string customInspector => "Rendering.HighDefinition.LitShaderGraphGUI";
// SubShader features
protected override bool supportDistortion => true;
protected override bool supportForward => false;
protected override bool supportPathtracing => !TargetsVFX();
protected override bool requireSplitLighting => litData.HasMaterialType(HDLitData.MaterialTypeMask.SubsurfaceScattering);
protected override SubShaderDescriptor GetSubShaderDescriptor()
{
var descriptor = base.GetSubShaderDescriptor();
descriptor.passes.Add(HDShaderPasses.GenerateLitDepthOnly(TargetsVFX(), systemData.tessellation));
descriptor.passes.Add(HDShaderPasses.GenerateGBuffer(TargetsVFX(), systemData.tessellation));
descriptor.passes.Add(HDShaderPasses.GenerateLitForward(TargetsVFX(), systemData.tessellation));
if (!systemData.tessellation) // Raytracing don't support tessellation neither VFX
descriptor.passes.Add(HDShaderPasses.GenerateLitRaytracingPrepass());
return descriptor;
}
protected override SubShaderDescriptor GetRaytracingSubShaderDescriptor()
{
var descriptor = base.GetRaytracingSubShaderDescriptor();
if (litData.HasMaterialType(HDLitData.MaterialTypeMask.SubsurfaceScattering))
descriptor.passes.Add(HDShaderPasses.GenerateRaytracingSubsurface());
return descriptor;
}
// Refraction
public static FieldDescriptor Refraction = new FieldDescriptor(string.Empty, "Refraction", "");
public static KeywordDescriptor RefractionKeyword = new KeywordDescriptor()
{
displayName = "Refraction Model",
referenceName = "_REFRACTION",
type = KeywordType.Enum,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Local,
entries = new KeywordEntry[]
{
new KeywordEntry() { displayName = "Off", referenceName = "" },
new KeywordEntry() { displayName = "Plane", referenceName = "PLANE" },
new KeywordEntry() { displayName = "Sphere", referenceName = "SPHERE" },
new KeywordEntry() { displayName = "Thin", referenceName = "THIN" },
}
};
public override void GetFields(ref TargetFieldContext context)
{
base.GetFields(ref context);
AddDistortionFields(ref context);
var descs = context.blocks.Select(x => x.descriptor);
bool hasRefraction = systemData.surfaceType == SurfaceType.Transparent && litData.refractionModel != ScreenSpaceRefraction.RefractionModel.None;
bool hasClearCoat = litData.clearCoat && litData.HasMaterialType(~HDLitData.MaterialTypeMask.ColoredTranslucent); // Colored translucent doesn't support clear coat
// Lit specific properties
context.AddField(DotsProperties, context.hasDotsProperties);
// Refraction
context.AddField(Refraction, hasRefraction);
// Misc
context.AddField(EnergyConservingSpecular, litData.energyConservingSpecular);
context.AddField(CoatMask, descs.Contains(BlockFields.SurfaceDescription.CoatMask) && context.pass.validPixelBlocks.Contains(BlockFields.SurfaceDescription.CoatMask) && hasClearCoat);
context.AddField(RayTracing, litData.rayTracing);
context.AddField(SpecularAA, lightingData.specularAA &&
context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.SpecularAAThreshold) &&
context.pass.validPixelBlocks.Contains(HDBlockFields.SurfaceDescription.SpecularAAScreenSpaceVariance));
}
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
bool hasTransmissionTint = litData.HasMaterialType(HDLitData.MaterialTypeMask.ColoredTranslucent);
bool hasTransmissionMask = litData.HasMaterialType(HDLitData.MaterialTypeMask.Translucent) || (litData.HasMaterialType(HDLitData.MaterialTypeMask.SubsurfaceScattering) && litData.sssTransmission);
bool hasRefraction = systemData.surfaceType == SurfaceType.Transparent && systemData.renderQueueType != HDRenderQueue.RenderQueueType.PreRefraction && litData.refractionModel != ScreenSpaceRefraction.RefractionModel.None;
bool hasClearCoat = litData.clearCoat && litData.HasMaterialType(~HDLitData.MaterialTypeMask.ColoredTranslucent); // Colored translucent doesn't support clear coat
// Vertex
base.GetActiveBlocks(ref context);
// Common
context.AddBlock(BlockFields.SurfaceDescription.CoatMask, hasClearCoat);
// Refraction
context.AddBlock(HDBlockFields.SurfaceDescription.RefractionIndex, hasRefraction);
context.AddBlock(HDBlockFields.SurfaceDescription.RefractionColor, hasRefraction);
context.AddBlock(HDBlockFields.SurfaceDescription.RefractionDistance, hasRefraction);
// Material
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, litData.HasMaterialType(HDLitData.MaterialTypeMask.Anisotropy));
context.AddBlock(HDBlockFields.SurfaceDescription.Anisotropy, litData.HasMaterialType(HDLitData.MaterialTypeMask.Anisotropy));
context.AddBlock(HDBlockFields.SurfaceDescription.SubsurfaceMask, litData.HasMaterialType(HDLitData.MaterialTypeMask.SubsurfaceScattering));
context.AddBlock(HDBlockFields.SurfaceDescription.TransmissionMask, hasTransmissionMask);
context.AddBlock(HDBlockFields.SurfaceDescription.TransmissionTint, hasTransmissionTint);
context.AddBlock(HDBlockFields.SurfaceDescription.Thickness, hasTransmissionMask || hasRefraction);
context.AddBlock(HDBlockFields.SurfaceDescription.DiffusionProfileHash, litData.HasMaterialType(HDLitData.MaterialTypeMask.SubsurfaceScattering) || litData.HasMaterialType(HDLitData.MaterialTypeMask.Translucent));
context.AddBlock(HDBlockFields.SurfaceDescription.IridescenceMask, litData.HasMaterialType(HDLitData.MaterialTypeMask.Iridescence));
context.AddBlock(HDBlockFields.SurfaceDescription.IridescenceThickness, litData.HasMaterialType(HDLitData.MaterialTypeMask.Iridescence));
context.AddBlock(BlockFields.SurfaceDescription.Specular, litData.HasMaterialType(HDLitData.MaterialTypeMask.SpecularColor));
context.AddBlock(BlockFields.SurfaceDescription.Metallic, litData.HasMaterialType(HDLitData.MaterialTypeMask.Standard) ||
litData.HasMaterialType(HDLitData.MaterialTypeMask.Anisotropy) ||
litData.HasMaterialType(HDLitData.MaterialTypeMask.Iridescence));
}
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
{
base.CollectShaderProperties(collector, generationMode);
HDSubShaderUtilities.AddRayTracingProperty(collector, litData.rayTracing);
// Refraction model property allow the material inspector to check if refraction is enabled in the shader.
collector.AddShaderProperty(new Vector1ShaderProperty
{
floatType = FloatType.Enum,
hidden = true,
value = (int)litData.refractionModel,
enumNames = Enum.GetNames(typeof(ScreenSpaceRefraction.RefractionModel)).ToList(),
overrideReferenceName = kRefractionModel,
});
var enumNames = new List<string>();
var enumValues = new List<int>();
foreach (HDLitData.MaterialTypeMask value in Enum.GetValues(typeof(HDLitData.MaterialTypeMask)))
{
if (litData.HasMaterialType(value))
{
enumNames.Add(value.ToString());
enumValues.Add((int)Mathf.Log((int)value, 2)); // Convert mask value to index
}
}
var defaultMaterialType = enumValues.First();
if (generationMode == GenerationMode.Preview && enumValues.Count > 1)
{
// For the SG preview, we select the first material type after standard to show it
if (enumValues[0] == (int)HDLitData.MaterialTypeMask.Standard)
defaultMaterialType = enumValues[1];
}
collector.AddShaderProperty(new Vector1ShaderProperty
{
floatType = FloatType.Enum,
enumType = EnumType.Enum,
enumNames = enumNames,
enumValues = enumValues,
hidden = true,
displayName = kMaterialID,
overrideReferenceName = kMaterialID,
value = defaultMaterialType,
});
collector.AddShaderProperty(new Vector1ShaderProperty
{
floatType = FloatType.Default,
hidden = true,
displayName = kMaterialTypeMask,
overrideReferenceName = kMaterialTypeMask,
value = (int)litData.materialTypeMask,
});
collector.AddBoolProperty(kTransmissionEnable, litData.sssTransmission);
if (litData.clearCoat && litData.HasMaterialType(~HDLitData.MaterialTypeMask.ColoredTranslucent))
collector.AddBoolProperty(kClearCoatEnabled, true);
}
static readonly List<string> materialFeatureSuffixes = new()
{
"SUBSURFACE_SCATTERING",
"TRANSMISSION",
"ANISOTROPY",
"IRIDESCENCE",
"SPECULAR_COLOR",
"COLORED_TRANSMISSION",
};
protected override void CollectPassKeywords(ref PassDescriptor pass)
{
base.CollectPassKeywords(ref pass);
pass.keywords.Add(RefractionKeyword);
foreach (var featureDefine in materialFeatureSuffixes)
{
pass.keywords.Add(new KeywordDescriptor
{
displayName = "Material Type",
referenceName = "_MATERIAL_FEATURE",
type = KeywordType.Enum,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Local,
stages = KeywordShaderStage.Fragment | (supportRaytracing ? KeywordShaderStage.RayTracing : 0),
entries = new KeywordEntry[]
{
new() { displayName = featureDefine, referenceName = featureDefine },
}
});
}
if (litData.clearCoat && litData.HasMaterialType(~HDLitData.MaterialTypeMask.ColoredTranslucent))
{
pass.keywords.Add(new KeywordDescriptor
{
displayName = "Cleat Coat",
referenceName = "_MATERIAL_FEATURE_CLEAR_COAT",
type = KeywordType.Boolean,
definition = KeywordDefinition.ShaderFeature,
scope = KeywordScope.Local,
stages = KeywordShaderStage.Fragment | (supportRaytracing ? KeywordShaderStage.RayTracing : 0),
});
}
}
protected override void AddInspectorPropertyBlocks(SubTargetPropertiesGUI blockList)
{
blockList.AddPropertyBlock(new LitSurfaceOptionPropertyBlock(litData));
if (systemData.surfaceType == SurfaceType.Transparent)
blockList.AddPropertyBlock(new DistortionPropertyBlock());
blockList.AddPropertyBlock(new AdvancedOptionsPropertyBlock());
}
protected override int ComputeMaterialNeedsUpdateHash()
{
int hash = base.ComputeMaterialNeedsUpdateHash();
unchecked
{
// hash must be 0 by default when we create a ShaderGraph, otherwise it's dirty when opened for the first time.
int h = (int)litData.materialTypeMask - (int)HDLitData.MaterialTypeMask.Standard;
hash = hash * 23 + h;
}
return hash;
}
internal override void MigrateTo(ShaderGraphVersion version)
{
base.MigrateTo(version);
if (version == ShaderGraphVersion.MaterialType)
UpgradeToMaterialType();
}
}
}