Skip to content
This repository was archived by the owner on Nov 30, 2020. It is now read-only.

Commit 09aafe8

Browse files
committed
Improved volume texture blending; Added support for ldr luts others than 1024x32
1 parent 1bdc68c commit 09aafe8

File tree

7 files changed

+173
-29
lines changed

7 files changed

+173
-29
lines changed

PostProcessing/Runtime/Effects/ColorGrading.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,8 @@ public sealed class ColorGrading : PostProcessEffectSettings
6161
[DisplayName("Gamma"), Min(0.001f), Tooltip("")]
6262
public FloatParameter toneCurveGamma = new FloatParameter { value = 1f };
6363

64-
[DisplayName("Lookup Texture"), Tooltip("Custom log-space lookup texture (strip format, e.g. 1024x32). EXR format is highly recommended or precision will be heavily degraded. Refer to the documentation for more information about how to create such a Lut.")]
65-
public TextureParameter logLut = new TextureParameter { value = null };
66-
6764
[DisplayName("Lookup Texture"), Tooltip("Custom lookup texture (strip format, e.g. 256x16) to apply before the rest of the color grading operators. If none is provided, a neutral one will be generated internally.")]
68-
public TextureParameter ldrLut = new TextureParameter { value = null }; // LDR only
65+
public TextureParameter ldrLut = new TextureParameter { value = null, defaultState = TextureParameterDefault.Lut2D }; // LDR only
6966

7067
[DisplayName("Temperature"), Range(-100f, 100f), Tooltip("Sets the white balance to a custom color temperature.")]
7168
public FloatParameter temperature = new FloatParameter { value = 0f };
@@ -309,7 +306,7 @@ void RenderHDRPipeline3D(PostProcessRenderContext context)
309306
// LUT (33^3 -> 32^3) but most of the time it's imperceptible.
310307
void RenderHDRPipeline2D(PostProcessRenderContext context)
311308
{
312-
// For the same reasons as in RenderHDRPipeline3D, regen LUT on evey frame
309+
// For the same reasons as in RenderHDRPipeline3D, regen LUT on every frame
313310
{
314311
CheckInternalStripLut();
315312

@@ -388,7 +385,7 @@ void RenderHDRPipeline2D(PostProcessRenderContext context)
388385
// LDR color pipeline is rendered to a 2D strip lut (works on every platform)
389386
void RenderLDRPipeline2D(PostProcessRenderContext context)
390387
{
391-
// For the same reasons as in RenderHDRPipeline3D, regen LUT on evey frame
388+
// For the same reasons as in RenderHDRPipeline3D, regen LUT on every frame
392389
{
393390
CheckInternalStripLut();
394391

@@ -426,11 +423,18 @@ void RenderLDRPipeline2D(PostProcessRenderContext context)
426423

427424
// Generate the lut
428425
context.command.BeginSample("LdrColorGradingLut2D");
426+
429427
var userLut = settings.ldrLut.value;
430428
if (userLut == null)
429+
{
431430
context.command.BlitFullscreenTriangle(BuiltinRenderTextureType.None, m_InternalLdrLut, lutSheet, (int)Pass.LutGenLDRFromScratch);
431+
}
432432
else
433+
{
434+
lutSheet.properties.SetVector(ShaderIDs.UserLut2D_Params, new Vector3(1f / userLut.width, 1f / userLut.height, userLut.height - 1f));
433435
context.command.BlitFullscreenTriangle(userLut, m_InternalLdrLut, lutSheet, (int)Pass.LutGenLDR);
436+
}
437+
434438
context.command.EndSample("LdrColorGradingLut2D");
435439
}
436440

PostProcessing/Runtime/ParameterOverride.cs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,73 @@ public override void Interp(Spline from, Spline to, float t)
215215
}
216216
}
217217

218+
public enum TextureParameterDefault
219+
{
220+
None,
221+
Black,
222+
White,
223+
Transparent,
224+
Lut2D
225+
}
226+
218227
[Serializable]
219228
public sealed class TextureParameter : ParameterOverride<Texture>
220229
{
230+
public TextureParameterDefault defaultState = TextureParameterDefault.Black;
231+
221232
public override void Interp(Texture from, Texture to, float t)
222233
{
223-
if (from == null || to == null)
234+
// Both are null, do nothing
235+
if (from == null && to == null)
224236
{
225-
base.Interp(from, to, t);
237+
value = null;
238+
return;
239+
}
240+
241+
// Both aren't null we're ready to blend
242+
if (from != null && to != null)
243+
{
244+
value = TextureLerper.instance.Lerp(from, to, t);
226245
return;
227246
}
228247

229-
value = TextureLerper.instance.Lerp(from, to, t);
248+
// One of them is null, blend to/from a default value is applicable
249+
{
250+
Texture defaultTexture;
251+
252+
switch (defaultState)
253+
{
254+
case TextureParameterDefault.Black:
255+
defaultTexture = RuntimeUtilities.blackTexture;
256+
break;
257+
case TextureParameterDefault.White:
258+
defaultTexture = RuntimeUtilities.whiteTexture;
259+
break;
260+
case TextureParameterDefault.Transparent:
261+
defaultTexture = RuntimeUtilities.transparentTexture;
262+
break;
263+
case TextureParameterDefault.Lut2D:
264+
// Find the current lut size
265+
int size = from != null ? from.height : to.height;
266+
defaultTexture = RuntimeUtilities.GetLutStrip(size);
267+
break;
268+
default:
269+
defaultTexture = null;
270+
break;
271+
}
272+
273+
if (from == null) from = defaultTexture;
274+
if (to == null) to = defaultTexture;
275+
276+
// defaultState could have been explicitly set to None
277+
if (from == null || to == null)
278+
{
279+
base.Interp(from, to, t);
280+
return;
281+
}
282+
283+
value = TextureLerper.instance.Lerp(from, to, t);
284+
}
230285
}
231286
}
232287
}

PostProcessing/Runtime/Utils/RuntimeUtilities.cs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public static Texture2D whiteTexture
2626
{
2727
if (m_WhiteTexture == null)
2828
{
29-
m_WhiteTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false);
29+
m_WhiteTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false) { name = "White Texture" };
3030
m_WhiteTexture.SetPixel(0, 0, Color.white);
3131
m_WhiteTexture.Apply();
3232
}
@@ -42,7 +42,7 @@ public static Texture2D blackTexture
4242
{
4343
if (m_BlackTexture == null)
4444
{
45-
m_BlackTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false);
45+
m_BlackTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false) { name = "Black Texture" };
4646
m_BlackTexture.SetPixel(0, 0, Color.black);
4747
m_BlackTexture.Apply();
4848
}
@@ -58,7 +58,7 @@ public static Texture2D transparentTexture
5858
{
5959
if (m_TransparentTexture == null)
6060
{
61-
m_TransparentTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false);
61+
m_TransparentTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false) { name = "Transparent Texture" };
6262
m_TransparentTexture.SetPixel(0, 0, Color.clear);
6363
m_TransparentTexture.Apply();
6464
}
@@ -67,6 +67,55 @@ public static Texture2D transparentTexture
6767
}
6868
}
6969

70+
static Dictionary<int, Texture2D> m_LutStrips = new Dictionary<int, Texture2D>();
71+
72+
public static Texture2D GetLutStrip(int size)
73+
{
74+
Texture2D texture;
75+
if (!m_LutStrips.TryGetValue(size, out texture))
76+
{
77+
int width = size * size;
78+
int height = size;
79+
var pixels = new Color[width * height];
80+
float inv = 1f / (size - 1f);
81+
82+
for (int z = 0; z < size; z++)
83+
{
84+
var offset = z * size;
85+
var b = z * inv;
86+
87+
for (int y = 0; y < size; y++)
88+
{
89+
var g = y * inv;
90+
91+
for (int x = 0; x < size; x++)
92+
{
93+
var r = x * inv;
94+
pixels[y * width + offset + x] = new Color(r, g, b);
95+
}
96+
}
97+
}
98+
99+
var format = TextureFormat.RGBAHalf;
100+
if (!format.IsSupported())
101+
format = TextureFormat.ARGB32;
102+
103+
texture = new Texture2D(size * size, size, format, false, true)
104+
{
105+
name = "Strip Lut" + size,
106+
hideFlags = HideFlags.DontSave,
107+
filterMode = FilterMode.Bilinear,
108+
wrapMode = TextureWrapMode.Clamp,
109+
anisoLevel = 0
110+
};
111+
texture.SetPixels(pixels);
112+
texture.Apply();
113+
m_LutStrips.Add(size, texture);
114+
}
115+
116+
return texture;
117+
}
118+
70119
#endregion
71120

72121
#region Rendering

PostProcessing/Runtime/Utils/ShaderIDs.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ static class ShaderIDs
100100
internal static readonly int Lut3D = Shader.PropertyToID("_Lut3D");
101101
internal static readonly int Lut3D_Params = Shader.PropertyToID("_Lut3D_Params");
102102
internal static readonly int Lut2D_Params = Shader.PropertyToID("_Lut2D_Params");
103+
internal static readonly int UserLut2D_Params = Shader.PropertyToID("_UserLut2D_Params");
103104
internal static readonly int PostExposure = Shader.PropertyToID("_PostExposure");
104105
internal static readonly int ColorBalance = Shader.PropertyToID("_ColorBalance");
105106
internal static readonly int ColorFilter = Shader.PropertyToID("_ColorFilter");

PostProcessing/Runtime/Utils/TextureFormatUtilities.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public static class TextureFormatUtilities
99
{
1010
static Dictionary<int, RenderTextureFormat> s_FormatAliasMap;
1111
static Dictionary<int, bool> s_SupportedRenderTextureFormats;
12+
static Dictionary<int, bool> s_SupportedTextureFormats;
1213

1314
static TextureFormatUtilities()
1415
{
@@ -70,13 +71,30 @@ static TextureFormatUtilities()
7071

7172
// In 2018.1 SystemInfo.SupportsRenderTextureFormat() generates garbage so we need to
7273
// cache its calls to avoid that...
73-
s_SupportedRenderTextureFormats = new Dictionary<int, bool>();
74-
var values = Enum.GetValues(typeof(RenderTextureFormat));
74+
{
75+
s_SupportedRenderTextureFormats = new Dictionary<int, bool>();
76+
var values = Enum.GetValues(typeof(RenderTextureFormat));
77+
78+
foreach (var format in values)
79+
{
80+
bool supported = SystemInfo.SupportsRenderTextureFormat((RenderTextureFormat)format);
81+
s_SupportedRenderTextureFormats.Add((int)format, supported);
82+
}
83+
}
7584

76-
foreach (var format in values)
85+
// Same for TextureFormat
7786
{
78-
bool supported = SystemInfo.SupportsRenderTextureFormat((RenderTextureFormat)format);
79-
s_SupportedRenderTextureFormats.Add((int)format, supported);
87+
s_SupportedTextureFormats = new Dictionary<int, bool>();
88+
var values = Enum.GetValues(typeof(TextureFormat));
89+
90+
foreach (var format in values)
91+
{
92+
if ((int)format < 0) // Crashes the runtime otherwise (!)
93+
continue;
94+
95+
bool supported = SystemInfo.SupportsTextureFormat((TextureFormat)format);
96+
s_SupportedTextureFormats.Add((int)format, supported);
97+
}
8098
}
8199
}
82100

@@ -107,5 +125,12 @@ internal static bool IsSupported(this RenderTextureFormat format)
107125
s_SupportedRenderTextureFormats.TryGetValue((int)format, out supported);
108126
return supported;
109127
}
128+
129+
internal static bool IsSupported(this TextureFormat format)
130+
{
131+
bool supported;
132+
s_SupportedTextureFormats.TryGetValue((int)format, out supported);
133+
return supported;
134+
}
110135
}
111136
}

PostProcessing/Runtime/Utils/TextureLerper.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,9 @@ internal Texture Lerp(Texture from, Texture to, float t)
109109
bool is3d = to is Texture3D
110110
|| (to is RenderTexture && ((RenderTexture)to).volumeDepth > 1);
111111

112-
RenderTexture rt = null;
112+
RenderTexture rt;
113113

114+
// 3D texture blending is a special case and only works on compute enabled platforms
114115
if (is3d)
115116
{
116117
int size = to.width;
@@ -126,18 +127,24 @@ internal Texture Lerp(Texture from, Texture to, float t)
126127
int groupSizeXY = Mathf.CeilToInt(size / 8f);
127128
int groupSizeZ = Mathf.CeilToInt(size / (RuntimeUtilities.isAndroidOpenGL ? 2f : 8f));
128129
m_Command.DispatchCompute(compute, kernel, groupSizeXY, groupSizeXY, groupSizeZ);
130+
return rt;
129131
}
130-
else
131-
{
132-
var format = TextureFormatUtilities.GetUncompressedRenderTextureFormat(to);
133-
rt = Get(format, to.width, to.height);
134132

135-
var sheet = m_PropertySheets.Get(m_Resources.shaders.texture2dLerp);
136-
sheet.properties.SetTexture(ShaderIDs.To, to);
137-
sheet.properties.SetFloat(ShaderIDs.Interp, t);
138-
139-
m_Command.BlitFullscreenTriangle(from, rt, sheet, 0);
140-
}
133+
// 2D texture blending
134+
// We could handle textures with different sizes by picking the biggest one to avoid
135+
// popping effects. This would work in most cases but will still pop if one texture is
136+
// wider but shorter than the other. Generally speaking you're expected to use same-size
137+
// textures anyway so we decided not to handle this case at the moment, especially since
138+
// it would waste a lot of texture memory as soon as you start using bigger textures
139+
// (snow ball effect).
140+
var format = TextureFormatUtilities.GetUncompressedRenderTextureFormat(to);
141+
rt = Get(format, to.width, to.height);
142+
143+
var sheet = m_PropertySheets.Get(m_Resources.shaders.texture2dLerp);
144+
sheet.properties.SetTexture(ShaderIDs.To, to);
145+
sheet.properties.SetFloat(ShaderIDs.Interp, t);
146+
147+
m_Command.BlitFullscreenTriangle(from, rt, sheet, 0);
141148

142149
return rt;
143150
}

PostProcessing/Shaders/Builtins/Lut2DBaker.shader

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Shader "Hidden/PostProcessing/Lut2DBaker"
99

1010
TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
1111
float4 _Lut2D_Params;
12+
float3 _UserLut2D_Params;
1213

1314
float3 _ColorBalance;
1415
float3 _ColorFilter;
@@ -97,7 +98,9 @@ Shader "Hidden/PostProcessing/Lut2DBaker"
9798

9899
float4 FragLDR(VaryingsDefault i) : SV_Target
99100
{
100-
float3 colorLinear = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord).rgb;
101+
// Note: user luts may not have the same size as the internal one
102+
float3 neutralColorLinear = GetLutStripValue(i.texcoordStereo, _Lut2D_Params);
103+
float3 colorLinear = ApplyLut2D(TEXTURE2D_PARAM(_MainTex, sampler_MainTex), neutralColorLinear, _UserLut2D_Params);
101104
float3 graded = ColorGradeLDR(colorLinear);
102105
return float4(graded, 1.0);
103106
}

0 commit comments

Comments
 (0)