Skip to content

Commit dd0e335

Browse files
AndrewSaraevUnityDeployer User
authored andcommitted
Support DGI mixed lights baking for HalfLuv and R11G11B10 radiance encodings. (#98)
1 parent 1aaf6ec commit dd0e335

File tree

2 files changed

+190
-5
lines changed

2 files changed

+190
-5
lines changed

com.unity.render-pipelines.high-definition/Runtime/Lighting/ProbeVolume/DynamicGI/ProbeVolumeDynamicGI.cs

Lines changed: 164 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Runtime.CompilerServices;
44
using System.Runtime.InteropServices;
5+
using Unity.Collections.LowLevel.Unsafe;
56
using UnityEngine.Experimental.Rendering;
67

78
using static UnityEngine.Rendering.HighDefinition.ProbePropagationBasis;
@@ -436,6 +437,157 @@ static Vector3 RgbFromLogluv(Vector3 vLogLuv)
436437
Mathf.Max(vRGB.z, 0f));
437438
}
438439

440+
static Vector3 LuvFromRgb(Vector3 vRGB)
441+
{
442+
Vector3 vResult;
443+
Vector3 Xp_Y_XYZp = LOG_LUV_ENCODE_MAT * vRGB;
444+
Xp_Y_XYZp = new Vector3(
445+
Mathf.Max(Xp_Y_XYZp.x, 1e-6f),
446+
Mathf.Max(Xp_Y_XYZp.y, 1e-6f),
447+
Mathf.Max(Xp_Y_XYZp.z, 1e-6f));
448+
vResult.x = Xp_Y_XYZp.x / Xp_Y_XYZp.z;
449+
vResult.y = Xp_Y_XYZp.y / Xp_Y_XYZp.z;
450+
float Le = Xp_Y_XYZp.y; // Raw range
451+
vResult.z = Le;
452+
return vResult;
453+
}
454+
455+
static Vector3 RgbFromLuv(Vector3 vLogLuv)
456+
{
457+
Vector3 Xp_Y_XYZp;
458+
Xp_Y_XYZp.y = vLogLuv.z; // Raw range
459+
Xp_Y_XYZp.z = Xp_Y_XYZp.y / vLogLuv.y;
460+
Xp_Y_XYZp.x = vLogLuv.x * Xp_Y_XYZp.z;
461+
Vector3 vRGB = LOG_LUV_DECODE_MAT * Xp_Y_XYZp;
462+
return new Vector3(
463+
Mathf.Max(vRGB.x, 0f),
464+
Mathf.Max(vRGB.y, 0f),
465+
Mathf.Max(vRGB.z, 0f));
466+
}
467+
468+
static uint EncodeSimpleUHalfFloat(float x)
469+
{
470+
x = Mathf.Clamp(x, Mathf.Pow(2f, -15f), Mathf.Pow(2f, 16f));
471+
472+
uint floatBits = UnsafeUtility.As<float, uint>(ref x);
473+
474+
uint floatFraction = floatBits & ((1u << 23) - 1u);
475+
uint floatExponent = floatBits >> 23;
476+
477+
uint halfFraction = floatFraction >> (23 - 11); // truncate.
478+
479+
// float bias: -127
480+
// half bias: -15
481+
// diff bias: -112.
482+
uint halfExponent = (floatExponent < 112u) ? 0u : (floatExponent - 112u);
483+
halfExponent = Math.Min(31u, halfExponent); // Clamp shouldnt be necessary.
484+
485+
return (halfExponent << 11) | halfFraction;
486+
}
487+
488+
static float DecodeSimpleUHalfFloat(uint halfBits)
489+
{
490+
uint halfExponent = halfBits >> 11;
491+
uint halfFraction = halfBits & ((1u << 11) - 1u);
492+
493+
uint floatFraction = halfFraction << (23 - 11);
494+
uint floatExponent = halfExponent + 112u;
495+
496+
uint floatBits = (floatExponent << 23) | floatFraction;
497+
498+
return UnsafeUtility.As<uint, float>(ref floatBits);
499+
}
500+
501+
static uint EncodeSimpleU10Float(float x)
502+
{
503+
x = Mathf.Clamp(x, Mathf.Pow(2f, -15f), Mathf.Pow(2f, 16f));
504+
505+
uint floatBits = UnsafeUtility.As<float, uint>(ref x);
506+
507+
uint floatFraction = floatBits & ((1u << 23) - 1u);
508+
uint floatExponent = floatBits >> 23;
509+
510+
uint halfFraction = floatFraction >> (23 - 5); // truncate.
511+
512+
// float bias: -127
513+
// half bias: -15
514+
// diff bias: -112.
515+
uint halfExponent = (floatExponent < 112u) ? 0u : (floatExponent - 112u);
516+
halfExponent = Math.Min(31u, halfExponent); // Clamp shouldnt be necessary.
517+
518+
return (halfExponent << 5) | halfFraction;
519+
}
520+
521+
static float DecodeSimpleU10Float(uint halfBits)
522+
{
523+
uint halfExponent = halfBits >> 5;
524+
uint halfFraction = halfBits & ((1u << 5) - 1u);
525+
526+
uint floatFraction = halfFraction << (23 - 5);
527+
uint floatExponent = halfExponent + 112u;
528+
529+
uint floatBits = (floatExponent << 23) | floatFraction;
530+
531+
return UnsafeUtility.As<uint, float>(ref floatBits);
532+
}
533+
534+
static uint EncodeSimpleU11Float(float x)
535+
{
536+
x = Mathf.Clamp(x, Mathf.Pow(2f, -15f), Mathf.Pow(2f, 16f));
537+
538+
uint floatBits = UnsafeUtility.As<float, uint>(ref x);
539+
540+
uint floatFraction = floatBits & ((1u << 23) - 1u);
541+
uint floatExponent = floatBits >> 23;
542+
543+
uint halfFraction = floatFraction >> (23 - 6); // truncate.
544+
545+
// float bias: -127
546+
// half bias: -15
547+
// diff bias: -112.
548+
uint halfExponent = (floatExponent < 112u) ? 0u : (floatExponent - 112u);
549+
halfExponent = Math.Min(31u, halfExponent); // Clamp shouldnt be necessary.
550+
551+
return (halfExponent << 6) | halfFraction;
552+
}
553+
554+
static float DecodeSimpleU11Float(uint halfBits)
555+
{
556+
uint halfExponent = halfBits >> 6;
557+
uint halfFraction = halfBits & ((1u << 6) - 1u);
558+
559+
uint floatFraction = halfFraction << (23 - 6);
560+
uint floatExponent = halfExponent + 112u;
561+
562+
uint floatBits = (floatExponent << 23) | floatFraction;
563+
564+
return UnsafeUtility.As<uint, float>(ref floatBits);
565+
}
566+
567+
static uint EncodeSimpleR11G11B10(Vector3 rgb)
568+
{
569+
uint r11 = EncodeSimpleU11Float(rgb.x);
570+
uint g11 = EncodeSimpleU11Float(rgb.y);
571+
uint b10 = EncodeSimpleU10Float(rgb.z);
572+
573+
return (r11 << 21)
574+
| (g11 << 10)
575+
| b10;
576+
}
577+
578+
internal static Vector3 DecodeSimpleR11G11B10(uint r11g11b10)
579+
{
580+
uint r11 = r11g11b10 >> 21;
581+
uint g11 = (r11g11b10 >> 10) & ((1u << 11) - 1u);
582+
uint b10 = r11g11b10 & ((1u << 10) - 1u);
583+
584+
return new Vector3(
585+
DecodeSimpleU11Float(r11),
586+
DecodeSimpleU11Float(g11),
587+
DecodeSimpleU10Float(b10)
588+
);
589+
}
590+
439591
internal static Vector3 DecodeLogLuv(uint value)
440592
{
441593
Vector3 logLuv;
@@ -445,6 +597,15 @@ internal static Vector3 DecodeLogLuv(uint value)
445597
return RgbFromLogluv(logLuv);
446598
}
447599

600+
internal static Vector3 DecodeHalfLuv(uint value)
601+
{
602+
Vector3 luv;
603+
luv.x = ((value >> 0) & 255) / 255.0f;
604+
luv.y = ((value >> 8) & 255) / 255.0f;
605+
luv.z = DecodeSimpleUHalfFloat(value >> 16);
606+
return RgbFromLuv(luv);
607+
}
608+
448609
internal void Allocate(RenderPipelineResources resources)
449610
{
450611
Cleanup(); // To avoid double alloc.
@@ -568,6 +729,8 @@ private void SetBasisKeywords(ProbeVolumeDynamicGIBasis basis, ProbeVolumeDynami
568729
}
569730
}
570731

732+
internal static bool IsRadianceEncodedInUint(ProbeVolumeDynamicGIRadianceEncoding encoding) => encoding != ProbeVolumeDynamicGIRadianceEncoding.RGBFloat;
733+
571734
static void SetRadianceEncodingKeywords(ComputeShader shader, ProbeVolumeDynamicGIRadianceEncoding encoding)
572735
{
573736
switch (encoding)
@@ -1181,7 +1344,7 @@ static bool InitializePropagationBuffers(ProbeVolumeHandle probeVolume, ProbeVol
11811344
propagationPipelineData.radianceEncoding = radianceEncoding;
11821345
}
11831346

1184-
changed |= radianceEncoding == ProbeVolumeDynamicGIRadianceEncoding.LogLuv
1347+
changed |= IsRadianceEncodedInUint(propagationPipelineData.radianceEncoding)
11851348
? EnsurePropagationBuffers<uint>(ref propagationPipelineData, hitNeighborAxisLengthOrOne, numAxis)
11861349
: EnsurePropagationBuffers<Vector3>(ref propagationPipelineData, hitNeighborAxisLengthOrOne, numAxis);
11871350

com.unity.render-pipelines.high-definition/Runtime/Lighting/ProbeVolume/ProbeVolume.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,14 +1309,36 @@ internal void CopyDirectLightingToMixed()
13091309
if (hitRadianceCache == null || !hitRadianceCache.IsValid() || hitRadianceCache.count != hits.Length)
13101310
return;
13111311

1312-
if (propagationPipelineData.radianceEncoding == ProbeVolumeDynamicGIRadianceEncoding.LogLuv)
1312+
if (ProbeVolumeDynamicGI.IsRadianceEncodedInUint(propagationPipelineData.radianceEncoding))
13131313
{
13141314
var hitRandiance = new uint[hits.Length];
13151315
hitRadianceCache.GetData(hitRandiance);
1316-
for (int i = 0; i < hits.Length; i++)
1316+
switch (propagationPipelineData.radianceEncoding)
13171317
{
1318-
var lighting = ProbeVolumeDynamicGI.DecodeLogLuv(hitRandiance[i]);
1319-
hits[i].mixedLighting = ProbeVolumeDynamicGI.PackEmission(lighting);
1318+
case ProbeVolumeDynamicGIRadianceEncoding.LogLuv:
1319+
for (int i = 0; i < hits.Length; i++)
1320+
{
1321+
var lighting = ProbeVolumeDynamicGI.DecodeLogLuv(hitRandiance[i]);
1322+
hits[i].mixedLighting = ProbeVolumeDynamicGI.PackEmission(lighting);
1323+
}
1324+
break;
1325+
case ProbeVolumeDynamicGIRadianceEncoding.HalfLuv:
1326+
for (int i = 0; i < hits.Length; i++)
1327+
{
1328+
var lighting = ProbeVolumeDynamicGI.DecodeHalfLuv(hitRandiance[i]);
1329+
hits[i].mixedLighting = ProbeVolumeDynamicGI.PackEmission(lighting);
1330+
}
1331+
break;
1332+
case ProbeVolumeDynamicGIRadianceEncoding.R11G11B10:
1333+
for (int i = 0; i < hits.Length; i++)
1334+
{
1335+
var lighting = ProbeVolumeDynamicGI.DecodeSimpleR11G11B10(hitRandiance[i]);
1336+
hits[i].mixedLighting = ProbeVolumeDynamicGI.PackEmission(lighting);
1337+
}
1338+
break;
1339+
default:
1340+
Debug.Assert(false);
1341+
return;
13201342
}
13211343
}
13221344
else

0 commit comments

Comments
 (0)