You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
12 KiB
299 lines
12 KiB
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
using Unity.Mathematics;
|
|
|
|
using RuntimeResources = UnityEngine.Rendering.ProbeReferenceVolume.RuntimeResources;
|
|
|
|
namespace UnityEngine.Rendering
|
|
{
|
|
static class ProbeVolumeConstantRuntimeResources
|
|
{
|
|
static ComputeBuffer m_SkySamplingDirectionsBuffer = null;
|
|
static ComputeBuffer m_AntiLeakDataBuffer = null;
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
internal static void GetRuntimeResources(ref RuntimeResources rr)
|
|
{
|
|
rr.SkyPrecomputedDirections = m_SkySamplingDirectionsBuffer;
|
|
rr.QualityLeakReductionData = m_AntiLeakDataBuffer;
|
|
}
|
|
|
|
internal static void Initialize()
|
|
{
|
|
if (m_SkySamplingDirectionsBuffer == null)
|
|
{
|
|
k_SkyDirections = GenerateSkyDirections();
|
|
m_SkySamplingDirectionsBuffer = new ComputeBuffer(k_SkyDirections.Length, 3 * sizeof(float));
|
|
m_SkySamplingDirectionsBuffer.SetData(k_SkyDirections);
|
|
}
|
|
|
|
if (m_AntiLeakDataBuffer == null)
|
|
{
|
|
m_AntiLeakDataBuffer = new ComputeBuffer(k_AntiLeakData.Length, sizeof(uint));
|
|
m_AntiLeakDataBuffer.SetData(k_AntiLeakData);
|
|
}
|
|
}
|
|
|
|
public static Vector3[] GetSkySamplingDirections()
|
|
{
|
|
return k_SkyDirections;
|
|
}
|
|
|
|
internal static void Cleanup()
|
|
{
|
|
CoreUtils.SafeRelease(m_SkySamplingDirectionsBuffer);
|
|
m_SkySamplingDirectionsBuffer = null;
|
|
|
|
CoreUtils.SafeRelease(m_AntiLeakDataBuffer);
|
|
m_AntiLeakDataBuffer = null;
|
|
}
|
|
|
|
#region Sky Directions Buffer generator
|
|
const int NB_SKY_PRECOMPUTED_DIRECTIONS = 255;
|
|
static Vector3[] k_SkyDirections = new Vector3[NB_SKY_PRECOMPUTED_DIRECTIONS];
|
|
|
|
static Vector3[] GenerateSkyDirections()
|
|
{
|
|
var skyDirections = new Vector3[NB_SKY_PRECOMPUTED_DIRECTIONS];
|
|
|
|
float sqrtNBpoints = Mathf.Sqrt((float)(NB_SKY_PRECOMPUTED_DIRECTIONS));
|
|
float phi = 0.0f;
|
|
float phiMax = 0.0f;
|
|
float thetaMax = 0.0f;
|
|
|
|
// Spiral based sampling on sphere
|
|
// See http://web.archive.org/web/20120331125729/http://www.math.niu.edu/~rusin/known-math/97/spherefaq
|
|
// http://www.math.vanderbilt.edu/saffeb/texts/161.pdf
|
|
for (int i=0; i < NB_SKY_PRECOMPUTED_DIRECTIONS; i++)
|
|
{
|
|
// theta from 0 to PI
|
|
// phi from 0 to 2PI
|
|
float h = -1.0f + (2.0f * i) / (NB_SKY_PRECOMPUTED_DIRECTIONS - 1.0f);
|
|
float theta = Mathf.Acos(h);
|
|
if (i == NB_SKY_PRECOMPUTED_DIRECTIONS - 1 || i==0)
|
|
phi = 0.0f;
|
|
else
|
|
phi = phi + 3.6f / sqrtNBpoints * 1.0f / (Mathf.Sqrt(1.0f-h*h));
|
|
|
|
Vector3 pointOnSphere = new Vector3(Mathf.Sin(theta) * Mathf.Cos(phi), Mathf.Sin(theta) * Mathf.Sin(phi), Mathf.Cos(theta));
|
|
|
|
pointOnSphere.Normalize();
|
|
skyDirections[i] = pointOnSphere;
|
|
|
|
phiMax = Mathf.Max(phiMax, phi);
|
|
thetaMax = Mathf.Max(thetaMax, theta);
|
|
}
|
|
|
|
return skyDirections;
|
|
}
|
|
#endregion
|
|
|
|
#region AntiLeak Buffer generator
|
|
#if UNITY_EDITOR
|
|
static uint3 GetSampleOffset(uint i)
|
|
{
|
|
return new uint3(i, i >> 1, i >> 2) & 1;
|
|
}
|
|
static int GetProbeIndex(int x, int y, int z)
|
|
{
|
|
return x + y * 2 + z * 4;
|
|
}
|
|
|
|
static uint BuildFace(int axis, int idx)
|
|
{
|
|
uint mask = 0;
|
|
int[] coords = new int[3];
|
|
coords[axis] = idx;
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
coords[(axis + 1) % 3] = i;
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
coords[(axis + 2) % 3] = j;
|
|
mask = mask | (uint)(1 << GetProbeIndex(coords[0], coords[1], coords[2]));
|
|
}
|
|
}
|
|
return mask;
|
|
}
|
|
|
|
static bool TryGetEdge(uint validityMask, uint samplingMask, out uint edge, out uint3 offset)
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if ((validityMask & (1 << i)) == 0)
|
|
continue;
|
|
|
|
uint3 p = GetSampleOffset((uint)i);
|
|
if (p.x == 0)
|
|
{
|
|
edge = (1u << i) | (1u << GetProbeIndex(1, (int)p.y, (int)p.z));
|
|
if ((validityMask & edge) == edge && (samplingMask & edge) == 0)
|
|
{
|
|
offset = 2 * p;
|
|
offset.x = 1;
|
|
return true;
|
|
}
|
|
}
|
|
if (p.y == 0)
|
|
{
|
|
edge = (1u << i) | (1u << GetProbeIndex((int)p.x, 1, (int)p.z));
|
|
if ((validityMask & edge) == edge && (samplingMask & edge) == 0)
|
|
{
|
|
offset = 2 * p;
|
|
offset.y = 1;
|
|
return true;
|
|
}
|
|
}
|
|
if (p.z == 0)
|
|
{
|
|
edge = (1u << i) | (1u << GetProbeIndex((int)p.x, (int)p.y, 1));
|
|
if ((validityMask & edge) == edge && (samplingMask & edge) == 0)
|
|
{
|
|
offset = 2 * p;
|
|
offset.z = 1;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
edge = 0;
|
|
offset = 0;
|
|
return false;
|
|
}
|
|
|
|
static List<uint3> ComputeMask(uint validityMask)
|
|
{
|
|
List<uint3> samples = new();
|
|
|
|
// Cube sample
|
|
if (validityMask == 0 || validityMask == 255)
|
|
{
|
|
samples.Add(1);
|
|
return samples;
|
|
}
|
|
|
|
// track which probes are sampled
|
|
uint samplingMask = 0;
|
|
|
|
// Find face sample
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
int axis = i / 2;
|
|
uint face = BuildFace(axis, i % 2);
|
|
if ((validityMask & face) == face) // all face is valid, sample it
|
|
{
|
|
uint3 offset = 0;
|
|
offset[axis] = (i % 2) == 0 ? 0u : 2u;
|
|
offset[(axis + 1) % 3] = 1;
|
|
offset[(axis + 2) % 3] = 1;
|
|
|
|
samples.Add(offset);
|
|
samplingMask = face;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Find edge samples
|
|
while (true)
|
|
{
|
|
if (!TryGetEdge(validityMask, samplingMask, out uint edge, out uint3 offset))
|
|
break;
|
|
|
|
samples.Add(offset);
|
|
samplingMask |= edge;
|
|
}
|
|
|
|
// Find single probe samples
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if (((1 << i) & (validityMask & ~samplingMask)) == 0)
|
|
continue;
|
|
samples.Add(2 * GetSampleOffset((uint)i));
|
|
samplingMask |= (uint)(1 << i);
|
|
}
|
|
|
|
return samples;
|
|
}
|
|
|
|
static uint PackSamplingDir(uint val)
|
|
{
|
|
// On a single axis there is up to 2 probes. A face or edge sample needs to sample in between the probes
|
|
// We encode 0 as sample first probe, 1 as sample between probe, 2 as sample second probe (2 bits)
|
|
// For faster decoding, we use a third bit that reduces ALU in shader
|
|
return /* 2 bits */ (val << 1) | /* 1 bit */ ((~val & 2) >> 1);
|
|
}
|
|
|
|
static uint InvalidSampleMask()
|
|
{
|
|
// This is a special code that results in no sampling in shader without any additional ALU
|
|
return 2 | (2 << 3) | (2 << 6);
|
|
}
|
|
|
|
static uint ComputeAntiLeakData(uint validityMask)
|
|
{
|
|
// This may generate more than 3 samples, but we limit to 3
|
|
var samples = ComputeMask(validityMask);
|
|
uint mask = 0;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
uint sampleMask;
|
|
if (i < samples.Count)
|
|
sampleMask = PackSamplingDir(samples[i].x) | (PackSamplingDir(samples[i].y) << 3) | (PackSamplingDir(samples[i].z) << 6);
|
|
else
|
|
sampleMask = InvalidSampleMask();
|
|
|
|
// 32bits - 9bits per samples (up to 3 samples)
|
|
// Each sample encodes sampling on each axis (3axis * 3bits)
|
|
// See PackSamplingDir for axis encoding
|
|
mask |= sampleMask << (9 * i);
|
|
}
|
|
|
|
return mask;
|
|
}
|
|
|
|
//[UnityEditor.MenuItem("Edit/Rendering/Global Illumination/Generate AntiLeak Buffer")]
|
|
static uint[] BuildAntiLeakDataArray()
|
|
{
|
|
uint[] antileak = new uint[256];
|
|
for (uint validityMask = 0; validityMask < 256; validityMask++)
|
|
antileak[validityMask] = ComputeAntiLeakData(validityMask);
|
|
|
|
string str = "static uint[] k_AntiLeakData = new uint[256] {\n";
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
str += " ";
|
|
for (int j = 0; j < 16; j++)
|
|
{
|
|
str += antileak[i * 16 + j] + (j == 15 ? ",\n" : ", ");
|
|
}
|
|
}
|
|
str += " };";
|
|
Debug.Log(str);
|
|
|
|
return antileak;
|
|
}
|
|
#endif
|
|
|
|
// This is autogenerated using the MenuItem above -- do not edit by hand
|
|
static uint[] k_AntiLeakData = new uint[256] {
|
|
38347995, 38347849, 38347852, 38347851, 38347873, 38347865, 38322764, 38322763, 38347876, 38324297, 38347868, 38324299, 38347875, 38324313, 38322780, 38347867,
|
|
38348041, 38347977, 38408780, 38408779, 38408801, 38408793, 69517900, 69517899, 38408804, 38324425, 38408796, 69519435, 38408803, 69519449, 69517916, 38408795,
|
|
38348044, 38410313, 38347980, 38410315, 38410337, 38410329, 38322892, 70304331, 38410340, 70305865, 38410332, 70305867, 38410339, 70305881, 70304348, 38410331,
|
|
38348043, 38410441, 38408908, 38347979, 38322955, 38409817, 69518028, 38322891, 38324491, 70305993, 38409820, 38324427, 38409827, 26351193, 25564764, 38323915,
|
|
38348065, 38421065, 38421068, 38421067, 38348001, 38421081, 38312161, 38388299, 38421092, 75810889, 38421084, 75810891, 38421091, 75810905, 38388316, 38421083,
|
|
38348057, 38421193, 38312217, 38416971, 38408929, 38347993, 69507297, 38312153, 38324505, 75811017, 38416988, 26358347, 38416995, 38324441, 69583452, 38320345,
|
|
38421260, 75896905, 38421196, 75896907, 38410465, 75896921, 38388428, 70369867, 75896932, 70305865, 75896924, 70305867, 75896931, 70305881, 70369884, 75896923,
|
|
38421259, 75897033, 38417100, 38421195, 38409953, 38410457, 69583564, 38377689, 75811083, 70305993, 75896412, 75811019, 75896419, 70306009, 70107740, 70301913,
|
|
38348068, 38422601, 38422604, 38422603, 38422625, 38422617, 76595788, 76595787, 38348004, 38310628, 38422620, 38389835, 38422627, 38389849, 76595804, 38422619,
|
|
38422793, 38422729, 76681804, 76681803, 76681825, 76681817, 69517900, 69517899, 38408932, 38389961, 76681820, 69584971, 76681827, 69584985, 69517916, 76681819,
|
|
38348060, 38310684, 38422732, 38418507, 38322972, 38418521, 76595916, 25573451, 38410468, 70292196, 38347996, 38310620, 38418531, 70371417, 38322908, 38318812,
|
|
38422795, 38418633, 76681932, 38422731, 76595979, 76682841, 69518028, 76595915, 38409956, 70371529, 38408924, 38376156, 76682851, 70109273, 69518044, 69513948,
|
|
38348067, 38310691, 38312227, 38422091, 38422753, 38422105, 76585185, 76661323, 38421220, 75797220, 38422108, 75876427, 38348003, 38310627, 38312163, 38311651,
|
|
38422809, 38422217, 76585241, 76689995, 76681953, 38422745, 69507297, 76585177, 38417124, 75876553, 76690012, 73779275, 38408931, 38389977, 69507299, 76593369,
|
|
38421276, 75797276, 38422220, 75905099, 38418657, 75905113, 76661452, 74564171, 75897060, 70292196, 38421212, 75797212, 38410467, 70292195, 38388444, 75805404,
|
|
38348059, 38310683, 38312219, 38422219, 38322971, 38418649, 25467163, 76650713, 38324507, 26252059, 38417116, 75862748, 38409955, 70371545, 69583580, 38347995,
|
|
};
|
|
#endregion
|
|
}
|
|
}
|