2026-04-16 오브젝트 그림자
This commit is contained in:
351
Assets/UmbraSoftShadows/Runtime/Scripts/UmbraProfile.cs
Normal file
351
Assets/UmbraSoftShadows/Runtime/Scripts/UmbraProfile.cs
Normal file
@@ -0,0 +1,351 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user