Skip to content

Commit f1ce949

Browse files
committed
feat: add SamplingScale option
close #269
1 parent 1ecb0b0 commit f1ce949

9 files changed

+132
-8
lines changed

Packages/src/Editor/UIEffectEditor.cs

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class UIEffect2Editor : Editor
2525

2626
private SerializedProperty _samplingFilter;
2727
private SerializedProperty _samplingIntensity;
28+
private SerializedProperty _samplingScale;
2829

2930
private SerializedProperty _transitionFilter;
3031
private SerializedProperty _transitionRate;
@@ -71,6 +72,7 @@ private void OnEnable()
7172

7273
_samplingFilter = serializedObject.FindProperty("m_SamplingFilter");
7374
_samplingIntensity = serializedObject.FindProperty("m_SamplingIntensity");
75+
_samplingScale = serializedObject.FindProperty("m_SamplingScale");
7476

7577
_transitionFilter = serializedObject.FindProperty("m_TransitionFilter");
7678
_transitionRate = serializedObject.FindProperty("m_TransitionRate");
@@ -145,6 +147,7 @@ public void DrawProperties()
145147
{
146148
EditorGUI.indentLevel++;
147149
EditorGUILayout.PropertyField(_samplingIntensity);
150+
EditorGUILayout.PropertyField(_samplingScale);
148151
EditorGUI.indentLevel--;
149152
}
150153

Packages/src/Editor/UIEffectReplicaEditor.cs

+3
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,22 @@ public class UIEffectReplicaEditor : Editor
1111
{
1212
private SerializedProperty _target;
1313
private SerializedProperty _useTargetTransform;
14+
private SerializedProperty _samplingScale;
1415
private Editor _uiEffectEditor;
1516

1617
private void OnEnable()
1718
{
1819
_target = serializedObject.FindProperty("m_Target");
1920
_useTargetTransform = serializedObject.FindProperty("m_UseTargetTransform");
21+
_samplingScale = serializedObject.FindProperty("m_SamplingScale");
2022
}
2123

2224
public override void OnInspectorGUI()
2325
{
2426
serializedObject.Update();
2527
EditorGUILayout.PropertyField(_target);
2628
EditorGUILayout.PropertyField(_useTargetTransform);
29+
EditorGUILayout.PropertyField(_samplingScale);
2730

2831
if (_target.objectReferenceValue)
2932
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System;
2+
using UnityEditor;
3+
using UnityEngine;
4+
5+
namespace Coffee.UIEffectInternal
6+
{
7+
[AttributeUsage(AttributeTargets.Field)]
8+
public sealed class PowerRangeAttribute : PropertyAttribute
9+
{
10+
public readonly float min;
11+
public readonly float max;
12+
public readonly float power;
13+
14+
public PowerRangeAttribute(float min, float max, float power)
15+
{
16+
this.min = min;
17+
this.max = max;
18+
this.power = power;
19+
}
20+
}
21+
22+
#if UNITY_EDITOR
23+
[CustomPropertyDrawer(typeof(PowerRangeAttribute))]
24+
internal sealed class RangeDrawer : PropertyDrawer
25+
{
26+
public override void OnGUI(Rect r, SerializedProperty property, GUIContent label)
27+
{
28+
var labelWidth = EditorGUIUtility.labelWidth;
29+
var attr = (PowerRangeAttribute)attribute;
30+
label = EditorGUI.BeginProperty(r, label, property);
31+
32+
EditorGUI.BeginChangeCheck();
33+
var rSlider = new Rect(r.x + labelWidth + 1, r.y, r.width - labelWidth - 57, r.height);
34+
var powValue = Mathf.Log(property.floatValue, attr.power);
35+
var powMin = Mathf.Log(attr.min, attr.power);
36+
var powMax = Mathf.Log(attr.max, attr.power);
37+
powValue = GUI.HorizontalSlider(rSlider, powValue, powMin, powMax);
38+
if (EditorGUI.EndChangeCheck())
39+
{
40+
property.floatValue = Mathf.Clamp(Mathf.Pow(attr.power, powValue), attr.min, attr.max);
41+
}
42+
43+
EditorGUI.BeginChangeCheck();
44+
EditorGUIUtility.labelWidth = r.width - 53;
45+
var newValue = EditorGUI.FloatField(r, label, property.floatValue);
46+
if (EditorGUI.EndChangeCheck())
47+
{
48+
property.floatValue = Mathf.Clamp(newValue, attr.min, attr.max);
49+
}
50+
51+
EditorGUI.EndProperty();
52+
EditorGUIUtility.labelWidth = labelWidth;
53+
}
54+
}
55+
#endif
56+
}

Packages/src/Runtime/Internal/Utilities/PowerRangeAttribute.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Packages/src/Runtime/UIEffect.cs

+21
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public class UIEffect : UIEffectBase
3737
[SerializeField]
3838
protected float m_SamplingIntensity = 0.5f;
3939

40+
[PowerRange(0.01f, 100f, 10f)]
41+
[SerializeField]
42+
protected float m_SamplingScale = 1f;
43+
4044
[SerializeField]
4145
protected TransitionFilter m_TransitionFilter = TransitionFilter.None;
4246

@@ -205,6 +209,22 @@ public float samplingIntensity
205209
}
206210
}
207211

212+
public float samplingScale
213+
{
214+
get => m_SamplingScale;
215+
set
216+
{
217+
value = Mathf.Clamp(value, 0.01f, 100);
218+
if (Mathf.Approximately(m_SamplingScale, value)) return;
219+
m_SamplingScale = value;
220+
ApplyContextToMaterial();
221+
}
222+
}
223+
224+
public override float actualSamplingScale => samplingFilter != SamplingFilter.None
225+
? Mathf.Clamp(m_SamplingScale, 0.01f, 100)
226+
: 1;
227+
208228
public TransitionFilter transitionFilter
209229
{
210230
get => m_TransitionFilter;
@@ -651,6 +671,7 @@ public void LoadPreset(UIEffect preset)
651671

652672
m_SamplingFilter = preset.m_SamplingFilter;
653673
m_SamplingIntensity = preset.m_SamplingIntensity;
674+
m_SamplingScale = preset.m_SamplingScale;
654675

655676
m_TransitionFilter = preset.m_TransitionFilter;
656677
m_TransitionRate = preset.m_TransitionRate;

Packages/src/Runtime/UIEffectBase.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public abstract class UIEffectBase : UIBehaviour, IMeshModifier, IMaterialModifi
3131

3232
public Graphic graphic => _graphic ? _graphic : _graphic = GetComponent<Graphic>();
3333
public virtual uint effectId => (uint)GetInstanceID();
34+
public virtual float actualSamplingScale => 1;
3435

3536
public virtual UIEffectContext context
3637
{
@@ -89,7 +90,8 @@ public virtual Material GetModifiedMaterial(Material baseMaterial)
8990
}
9091

9192
Profiler.BeginSample("(UIE)[UIEffect] GetModifiedMaterial");
92-
var hash = new Hash128((uint)baseMaterial.GetInstanceID(), effectId, 0, 0);
93+
var samplingScaleId = (uint)(Mathf.InverseLerp(0.01f, 100, actualSamplingScale) * uint.MaxValue);
94+
var hash = new Hash128((uint)baseMaterial.GetInstanceID(), effectId, samplingScaleId, 0);
9395
if (!MaterialRepository.Valid(hash, _material))
9496
{
9597
Profiler.BeginSample("(UIE)[UIEffect] GetModifiedMaterial > Get or create material");
@@ -199,7 +201,7 @@ public virtual void ApplyContextToMaterial()
199201
{
200202
if (!isActiveAndEnabled || context == null) return;
201203

202-
context.ApplyToMaterial(_material);
204+
context.ApplyToMaterial(_material, actualSamplingScale);
203205

204206
#if UNITY_EDITOR
205207
UIEffectProjectSettings.shaderRegistry.RegisterVariant(_material, "UI > UIEffect");

Packages/src/Runtime/UIEffectContext.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public class UIEffectContext
2323
private static readonly int s_ColorValue = Shader.PropertyToID("_ColorValue");
2424
private static readonly int s_ColorIntensity = Shader.PropertyToID("_ColorIntensity");
2525
private static readonly int s_SamplingIntensity = Shader.PropertyToID("_SamplingIntensity");
26+
private static readonly int s_SamplingScale = Shader.PropertyToID("_SamplingScale");
2627
private static readonly int s_TransitionRate = Shader.PropertyToID("_TransitionRate");
2728
private static readonly int s_TransitionReverse = Shader.PropertyToID("_TransitionReverse");
2829
private static readonly int s_TransitionTex = Shader.PropertyToID("_TransitionTex");
@@ -189,7 +190,7 @@ public void CopyFrom(UIEffectContext preset)
189190
shadowEffectOnOrigin = preset.shadowEffectOnOrigin;
190191
}
191192

192-
public void ApplyToMaterial(Material material)
193+
public void ApplyToMaterial(Material material, float actualSamplingScale = 1f)
193194
{
194195
if (!material) return;
195196

@@ -205,6 +206,7 @@ public void ApplyToMaterial(Material material)
205206
material.SetFloat(s_ColorIntensity, Mathf.Clamp01(colorIntensity));
206207

207208
material.SetFloat(s_SamplingIntensity, Mathf.Clamp01(samplingIntensity));
209+
material.SetFloat(s_SamplingScale, actualSamplingScale);
208210

209211
material.SetFloat(s_TransitionRate, Mathf.Clamp01(transitionRate));
210212
material.SetInt(s_TransitionReverse, transitionReverse ? 1 : 0);

Packages/src/Runtime/UIEffectReplica.cs

+20
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ public class UIEffectReplica : UIEffectBase
88
[SerializeField] private UIEffect m_Target;
99
[SerializeField] private bool m_UseTargetTransform = true;
1010

11+
[PowerRange(0.01f, 100, 10f)]
12+
[SerializeField]
13+
protected float m_SamplingScale = 1f;
14+
1115
private UIEffect _currentTarget;
1216
private Matrix4x4 _prevTransformHash;
1317

@@ -35,6 +39,22 @@ public bool useTargetTransform
3539
}
3640
}
3741

42+
public float samplingScale
43+
{
44+
get => m_SamplingScale;
45+
set
46+
{
47+
value = Mathf.Clamp(value, 0.01f, 100);
48+
if (Mathf.Approximately(m_SamplingScale, value)) return;
49+
m_SamplingScale = value;
50+
ApplyContextToMaterial();
51+
}
52+
}
53+
54+
public override float actualSamplingScale => target && target.samplingFilter != SamplingFilter.None
55+
? Mathf.Clamp(m_SamplingScale, 0.01f, 100)
56+
: 1;
57+
3858
public override uint effectId => target ? target.effectId : 0;
3959
public override UIEffectContext context => target && target.isActiveAndEnabled ? target.context : null;
4060

Packages/src/Shaders/UIEffect.cginc

+11-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ uniform float _ToneIntensity;
66
uniform half4 _ColorValue;
77
uniform float _ColorIntensity;
88
uniform float _SamplingIntensity;
9+
uniform float _SamplingScale;
910
uniform sampler2D _TransitionTex;
1011
uniform float4 _TransitionTex_ST;
1112
uniform float _TransitionRate;
@@ -41,6 +42,11 @@ uniform float _TargetSoftness;
4142
* step(uvMask.x, uv.x) * step(uv.x, uvMask.z) \
4243
* step(uvMask.y, uv.y) * step(uv.y, uvMask.w)
4344

45+
float2 texel_size()
46+
{
47+
return _MainTex_TexelSize.xy * _SamplingScale;
48+
}
49+
4450
float3 rgb_to_hsv(float3 c)
4551
{
4652
const float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
@@ -243,7 +249,7 @@ half4 apply_sampling_filter(float2 uv, const float4 uvMask, const float2 uvLocal
243249
float4 o = 0;
244250
float sum = 0;
245251
float2 shift = 0;
246-
const half2 blur = _MainTex_TexelSize.xy * _SamplingIntensity * 2;
252+
const half2 blur = texel_size() * _SamplingIntensity * 2;
247253
for (int x = 0; x < KERNEL_SIZE; x++)
248254
{
249255
shift.x = blur.x * (float(x) - KERNEL_SIZE / 2);
@@ -381,13 +387,13 @@ half4 uieffect(float2 uv, const float4 uvMask, const float2 uvLocal)
381387
// Sampling.Pixelation
382388
#if SAMPLING_PIXELATION
383389
{
384-
const half2 pixelSize = max(2, (1 - lerp(0.5, 0.95, _SamplingIntensity)) * _MainTex_TexelSize.zw);
390+
const half2 pixelSize = max(2, (1 - lerp(0.5, 0.95, _SamplingIntensity)) / texel_size());
385391
uv = round(uv * pixelSize) / pixelSize;
386392
}
387393
// Sampling.RgbShift
388394
#elif SAMPLING_RGB_SHIFT
389395
{
390-
const half2 offset = half2(_SamplingIntensity * _MainTex_TexelSize.x * 20, 0);
396+
const half2 offset = half2(_SamplingIntensity * texel_size().x * 20, 0);
391397
const half2 r = uieffect_internal(uv + offset, uvMask, uvLocal).ra;
392398
const half2 g = uieffect_internal(uv, uvMask, uvLocal).ga;
393399
const half2 b = uieffect_internal(uv - offset, uvMask, uvLocal).ba;
@@ -397,8 +403,8 @@ half4 uieffect(float2 uv, const float4 uvMask, const float2 uvLocal)
397403
#elif SAMPLING_EDGE_LUMINANCE || SAMPLING_EDGE_ALPHA
398404
{
399405
// Pixel size
400-
const float dx = _MainTex_TexelSize.x;
401-
const float dy = _MainTex_TexelSize.y;
406+
const float dx = texel_size().x;
407+
const float dy = texel_size().y;
402408

403409
// Pixel values around the current pixel (3x3, 8 neighbors)
404410
const float2 uv00 = uv + half2(-dx, -dy);

0 commit comments

Comments
 (0)