Files
Shopping_UnityVR/Assets/UmbraSoftShadows/Runtime/Scripts/UmbraProfile.cs
2026-04-16 04:58:10 +09:00

351 lines
14 KiB
C#

using UnityEngine;
namespace Umbra {
public enum ShadowSource {
UnityShadows,
UmbraShadows,
OnlyContactShadows
}
public enum ContactShadowsInjectionPoint {
ShadowTexture,
AfterOpaque
}
public enum UmbraPreset {
[InspectorName("")]
None = 0,
Hard = 10,
Soft = 20,
Smooth = 30,
ExtraSmooth = 40,
Blurred = 50,
Fast = 60
}
public enum BlurType {
[InspectorName("Gaussian (15 taps, 2 passes)")]
Gaussian15 = 10,
[InspectorName("Gaussian (5 taps, 2 passes)")]
Gaussian5 = 20,
[InspectorName("Box Blur (9 taps, 1 pass)")]
Box = 30
}
public enum NormalSource {
ReconstructFromDepth,
NormalsPass,
[InspectorName("GBuffer Normals")]
GBufferNormals
}
public enum LoopStep {
Default,
x2,
x3
}
public enum Style {
Default,
Textured
}
[CreateAssetMenu(fileName = "UmbraProfile", menuName = "Umbra Profile", order = 251)]
[HelpURL("https://kronnect.com/docs/umbra/")]
public class UmbraProfile : ScriptableObject {
[Tooltip("Which shadow generation system should be used")]
public ShadowSource shadowSource = ShadowSource.UmbraShadows;
[Tooltip("Translates to the number of shadow map samples used to resolve shadows")]
[Range(1, 64)]
public int sampleCount = 16;
[Tooltip("Number of samples to early out if shadow is already fully resolved")]
[Range(1, 64)]
public int earlyOutSamples = 32;
[Tooltip("Size of the directional light which influences the penumbra size")]
[Range(0f, 32)]
public float lightSize = 6;
[Tooltip("Makes shadows sharper nearer to the occluder")]
public bool enableContactHardening = true;
[Tooltip("Makes shadows sharper and stronger near the occluder")]
[Range(0, 1)]
public float contactStrength = 0.5f;
[Tooltip("Usual value is 5. Modify to alter the shadow edge appearance.")]
public float contactStrengthKnee = 0.0001f;
[Tooltip("Makes shadows smoother when far from occluder")]
[Range(1, 16)]
public float distantSpread = 1f;
[Tooltip("Number of shadow map samples to find occluders which improve the penumbra radius calculation")]
[Range(1, 64)]
public int occludersCount = 8;
[Tooltip("Multiplier to the occluder search radius in texture space. A higher value creates more diffused penumbra.")]
public float occludersSearchRadius = 8f;
[Tooltip("Number of blur passes. Each blur pass increases shadow softness but reduces performance.")]
[Range(0, 3)]
public int blurIterations;
[Tooltip("Specifies the blur method. Gaussian blur uses two passes per iteration and produces smoother results.")]
public BlurType blurType = BlurType.Gaussian15;
[Tooltip("Blur kerner radius multiplier. Improves softness but can introduce artifacts")]
[Range(0.5f, 5)]
public float blurSpread = 1f;
[Tooltip("Increases the contrast on the shadow border to create sharper shadows when blur is used")]
[Range(0, 1)]
public float blurEdgeSharpness;
[Tooltip("Strength of the edge weight when blurring")]
public float blurEdgeTolerance = 5f;
[Tooltip("Reduces blur on distance from camera")]
public float blurDepthAttenStart = 50;
[Tooltip("Blur reduction intensity")]
public float blurDepthAttenLength = 50;
[Tooltip("Blur reduction when viewing shadow from a grazing angle")]
[Range(0, 1)]
public float blurGrazingAttenuation;
public bool blendCascades;
[Range(1, 10)]
public int posterization = 1;
public float cascade1BlendingStrength = 0.1f;
public float cascade2BlendingStrength = 0.1f;
public float cascade3BlendingStrength = 0.1f;
[Tooltip("Manual adjustment of shadow smoothness multiplier for this cascade")]
public float cascade1Scale = 1f;
[Tooltip("Manual adjustment of shadow smoothness multiplier for this cascade")]
public float cascade2Scale = 1f;
[Tooltip("Manual adjustment of shadow smoothness multiplier for this cascade")]
public float cascade3Scale = 1f;
[Tooltip("Manual adjustment of shadow smoothness multiplier for this cascade")]
public float cascade4Scale = 1f;
[Tooltip("Method used to obtain surface normals. Reconstruct from depth is fastest, normals pass is more accurate, and GBuffer normals (deferred only) uses existing GBuffer data.")]
public NormalSource normalsSource = NormalSource.ReconstructFromDepth;
/// <summary>
/// Gets the effective normals source, falling back to ReconstructFromDepth when GBufferNormals is selected but not in deferred mode
/// </summary>
public NormalSource effectiveNormalsSource =>
normalsSource == NormalSource.GBufferNormals && !UmbraSoftShadows.isDeferred
? NormalSource.ReconstructFromDepth
: normalsSource;
[Tooltip("Reduces the number of samples while keeping the shadow size")]
public LoopStep loopStepOptimization = LoopStep.Default;
[Tooltip("Resolves shadowmap every two frames, reusing the result from previous frame")]
public bool frameSkipOptimization;
[Tooltip("Distance threshold - if camera has moved this distance from previous frame, ignore cached shadowmap")]
public float skipFrameMaxCameraDisplacement = 0.1f;
[Tooltip("Rotation threshold - if camera has rotated this angle from previous frame, ignore cached shadowmap")]
public float skipFrameMaxCameraRotation = 5f;
[Tooltip("Resolves screen space shadows in a reduced buffer of half of screen size")]
public bool downsample;
[Tooltip("Forces a depth prepass so depth and normals are available even for forward-only materials (useful in Deferred when using forward only materials).")]
public bool forceDepthPrepass;
[Tooltip("Prevents shadow blurring on geometry edges")]
public bool preserveEdges = true;
[Tooltip("Stylized look for shadows")]
public Style style = Style.Default;
[Tooltip("Optional mask texture to create stylized shadows")]
public Texture2D maskTexture;
public float maskScale = 1f;
public bool contactShadows;
[Range(0, 1)]
public float contactShadowsIntensityMultiplier = 0.85f;
public ContactShadowsInjectionPoint contactShadowsInjectionPoint = ContactShadowsInjectionPoint.ShadowTexture;
public ContactShadowsInjectionPoint actualContactShadowsInjectionPoint => shadowSource == ShadowSource.OnlyContactShadows || contactShadowsInjectionPoint == ContactShadowsInjectionPoint.AfterOpaque ? ContactShadowsInjectionPoint.AfterOpaque : contactShadowsInjectionPoint;
[Range(1, 64)]
public int contactShadowsSampleCount = 16;
public float contactShadowsStepping = 0.01f;
public float contactShadowsThicknessNear = 0.5f;
public float contactShadowsThicknessDistanceMultiplier;
public float contactShadowsJitter = 0.3f;
[Range(0, 1)]
[Tooltip("Attenuates shadow intensity with distance to occluder")]
public float contactShadowsDistanceFade = 0.75f;
public float contactShadowsStartDistance;
public float contactShadowsStartDistanceFade = 0.01f;
[Tooltip("Adds an offset to the pixel position to avoid self-occlusion")]
[Range(0.0001f, 0.25f)]
public float contactShadowsNormalBias = 0.1f;
[Tooltip("Attenuates contact shadows on the edges of screen")]
[Range(0, 0.5f)]
public float contactShadowsVignetteSize = 0.15f;
[Tooltip("Adds an offset to the pixel position to avoid self-occlusion")]
[Range(0f, 1f)]
public float contactShadowsBias = 0.001f;
[Tooltip("Bias applied at far distances. Use only if self-shadowing occurs on certain surfaces.")]
[Range(0, 1)]
public float contactShadowsBiasFar = 0.4f;
[Tooltip("Softens the edges of contact shadows. Higher values create softer edges.")]
[Range(0.01f, 0.5f)]
public float contactShadowsEdgeSoftness = 0.1f;
[Tooltip("Enables soft edges for contact shadows. When disabled, shadows have hard edges for better performance.")]
public bool contactShadowsSoftEdges;
[Tooltip("Makes contact shadows planar by ignoring the Y component of the light direction. Useful for ground shadows.")]
public bool contactShadowsPlanarShadows;
[Tooltip("Adds an extra pass after opaque with custom colored shadows")]
public bool overlayShadows;
public float overlayShadowsIntensity = 0.5f;
[ColorUsage(showAlpha: false, hdr: false)]
public Color overlayShadowsColor = Color.black;
[Tooltip("Enables a receiver plane to cast shadows from transparent objects. Check demo scene Transparent Receiver for an example.")]
public bool transparentReceiverPlane;
public float receiverPlaneAltitude;
void OnValidate() {
blurDepthAttenLength = Mathf.Max(0.001f, blurDepthAttenLength);
blurEdgeTolerance = Mathf.Max(0, blurEdgeTolerance);
blurDepthAttenStart = Mathf.Max(0, blurDepthAttenStart);
blurDepthAttenLength = Mathf.Max(0, blurDepthAttenLength);
blurGrazingAttenuation = Mathf.Max(0, blurGrazingAttenuation);
occludersSearchRadius = Mathf.Max(0.01f, occludersSearchRadius);
contactStrengthKnee = Mathf.Max(0.0001f, contactStrengthKnee);
cascade1BlendingStrength = Mathf.Max(0.01f, cascade1BlendingStrength);
cascade2BlendingStrength = Mathf.Max(0.01f, cascade2BlendingStrength);
cascade3BlendingStrength = Mathf.Max(0.01f, cascade3BlendingStrength);
cascade1Scale = Mathf.Max(0, cascade1Scale);
cascade2Scale = Mathf.Max(0, cascade2Scale);
cascade3Scale = Mathf.Max(0, cascade3Scale);
cascade4Scale = Mathf.Max(0, cascade4Scale);
maskScale = Mathf.Max(maskScale, 0);
skipFrameMaxCameraRotation = Mathf.Max(skipFrameMaxCameraRotation, 0);
skipFrameMaxCameraDisplacement = Mathf.Max(skipFrameMaxCameraDisplacement, 0);
contactShadowsStepping = Mathf.Max(0.0001f, contactShadowsStepping);
contactShadowsThicknessNear = Mathf.Max(0.0f, contactShadowsThicknessNear);
contactShadowsThicknessDistanceMultiplier = Mathf.Max(0.0f, contactShadowsThicknessDistanceMultiplier);
contactShadowsJitter = Mathf.Max(0f, contactShadowsJitter);
contactShadowsStartDistance = Mathf.Max(0, contactShadowsStartDistance);
contactShadowsStartDistanceFade = Mathf.Max(0.00001f, contactShadowsStartDistanceFade);
overlayShadowsIntensity = Mathf.Max(0, overlayShadowsIntensity);
}
public void ApplyPreset(UmbraPreset preset) {
shadowSource = ShadowSource.UmbraShadows;
switch (preset) {
case UmbraPreset.Fast:
sampleCount = 12;
lightSize = 12;
occludersCount = 6;
occludersSearchRadius = 5f;
enableContactHardening = true;
contactStrength = 0.5f;
contactStrengthKnee = 0.0001f;
blurIterations = 0;
distantSpread = 1f;
break;
case UmbraPreset.Hard:
sampleCount = 1;
lightSize = 0.5f;
enableContactHardening = false;
blurIterations = 1;
blurType = BlurType.Box;
blurSpread = 1f;
blurEdgeTolerance = 5f;
blurEdgeSharpness = 1f;
blurDepthAttenStart = 75;
blurDepthAttenLength = 50;
blurGrazingAttenuation = 0;
break;
case UmbraPreset.Soft:
sampleCount = 16;
lightSize = 8;
enableContactHardening = true;
occludersCount = 8;
occludersSearchRadius = 8f;
contactStrength = 0.5f;
contactStrengthKnee = 0.0001f;
distantSpread = 1f;
blurIterations = 0;
break;
case UmbraPreset.Smooth:
sampleCount = 16;
lightSize = 13;
enableContactHardening = true;
occludersCount = 9;
occludersSearchRadius = 8f;
contactStrength = 0.5f;
contactStrengthKnee = 0.0001f;
distantSpread = 1.2f;
blurIterations = 0;
break;
case UmbraPreset.ExtraSmooth:
sampleCount = 20;
lightSize = 16;
enableContactHardening = true;
occludersCount = 16;
occludersSearchRadius = 10;
contactStrength = 0.8f;
contactStrengthKnee = 0.0001f;
distantSpread = 1.4f;
blurIterations = 0;
break;
case UmbraPreset.Blurred:
sampleCount = 32;
lightSize = 16;
enableContactHardening = true;
occludersCount = 24;
occludersSearchRadius = 16;
contactStrength = 0.4f;
contactStrengthKnee = 0.0001f;
blurIterations = 0;
distantSpread = 2f;
break;
}
}
}
}