initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
|
@ -0,0 +1,35 @@
|
|||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UnityEngine.Rendering.Universal
|
||||
{
|
||||
[BurstCompile]
|
||||
struct LightExtractionJob : IJobFor
|
||||
{
|
||||
[ReadOnly]
|
||||
public NativeArray<VisibleLight> lights;
|
||||
|
||||
public NativeArray<LightType> lightTypes;
|
||||
|
||||
public NativeArray<float> radiuses;
|
||||
|
||||
public NativeArray<float3> directions;
|
||||
|
||||
public NativeArray<float3> positions;
|
||||
|
||||
public NativeArray<float> coneRadiuses;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var light = lights[index];
|
||||
var localToWorldMatrix = (float4x4)light.localToWorldMatrix;
|
||||
lightTypes[index] = light.lightType;
|
||||
radiuses[index] = light.range;
|
||||
directions[index] = localToWorldMatrix.c2.xyz;
|
||||
positions[index] = localToWorldMatrix.c3.xyz;
|
||||
coneRadiuses[index] = math.tan(math.radians(light.spotAngle * 0.5f)) * light.range;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7a39173dadb4c402d9d337545c6e8bd0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UnityEngine.Rendering.Universal
|
||||
{
|
||||
struct LightMinMaxZ
|
||||
{
|
||||
public float minZ;
|
||||
public float maxZ;
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
struct MinMaxZJob : IJobFor
|
||||
{
|
||||
public float4x4 worldToViewMatrix;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<VisibleLight> lights;
|
||||
public NativeArray<LightMinMaxZ> minMaxZs;
|
||||
public NativeArray<float> meanZs;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var light = lights[index];
|
||||
var lightToWorld = (float4x4)light.localToWorldMatrix;
|
||||
var originWS = lightToWorld.c3.xyz;
|
||||
var originVS = math.mul(worldToViewMatrix, math.float4(originWS, 1)).xyz;
|
||||
originVS.z *= -1;
|
||||
|
||||
var minMax = new LightMinMaxZ
|
||||
{
|
||||
minZ = originVS.z - light.range,
|
||||
maxZ = originVS.z + light.range
|
||||
};
|
||||
|
||||
if (light.lightType == LightType.Spot)
|
||||
{
|
||||
// Based on https://iquilezles.org/www/articles/diskbbox/diskbbox.htm
|
||||
var angleA = math.radians(light.spotAngle) * 0.5f;
|
||||
float cosAngleA = math.cos(angleA);
|
||||
float coneHeight = light.range * cosAngleA;
|
||||
float3 spotDirectionWS = lightToWorld.c2.xyz;
|
||||
var endPointWS = originWS + spotDirectionWS * coneHeight;
|
||||
var endPointVS = math.mul(worldToViewMatrix, math.float4(endPointWS, 1)).xyz;
|
||||
endPointVS.z *= -1;
|
||||
var angleB = math.PI * 0.5f - angleA;
|
||||
var coneRadius = light.range * cosAngleA * math.sin(angleA) / math.sin(angleB);
|
||||
var a = endPointVS - originVS;
|
||||
var e = math.sqrt(1.0f - a.z * a.z / math.dot(a, a));
|
||||
|
||||
// `-a.z` and `a.z` is `dot(a, {0, 0, -1}).z` and `dot(a, {0, 0, 1}).z` optimized
|
||||
// `cosAngleA` is multiplied by `coneHeight` to avoid normalizing `a`, which we know has length `coneHeight`
|
||||
if (-a.z < coneHeight * cosAngleA) minMax.minZ = math.min(originVS.z, endPointVS.z - e * coneRadius);
|
||||
if (a.z < coneHeight * cosAngleA) minMax.maxZ = math.max(originVS.z, endPointVS.z + e * coneRadius);
|
||||
}
|
||||
|
||||
minMax.minZ = math.max(minMax.minZ, 0);
|
||||
minMax.maxZ = math.max(minMax.maxZ, 0);
|
||||
minMaxZs[index] = minMax;
|
||||
meanZs[index] = (minMax.minZ + minMax.maxZ) / 2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c7144b5b3e5194263a2f290811e97974
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
|
||||
namespace UnityEngine.Rendering.Universal
|
||||
{
|
||||
// This could be multi-threaded if profiling shows need
|
||||
[BurstCompile]
|
||||
unsafe struct RadixSortJob : IJob
|
||||
{
|
||||
public NativeArray<uint> keys;
|
||||
public NativeArray<int> indices;
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
var counts = new NativeArray<int>(256, Allocator.Temp);
|
||||
var n = indices.Length / 2;
|
||||
|
||||
for (var i = 0; i < n; i++)
|
||||
{
|
||||
indices[i] = i;
|
||||
}
|
||||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
int currentOffset, nextOffset;
|
||||
|
||||
for (var j = 0; j < 256; j++)
|
||||
{
|
||||
counts[j] = 0;
|
||||
}
|
||||
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
currentOffset = 0;
|
||||
nextOffset = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentOffset = n;
|
||||
nextOffset = 0;
|
||||
}
|
||||
|
||||
for (var j = 0; j < n; j++)
|
||||
{
|
||||
var key = keys[currentOffset + j];
|
||||
var bucket = (key >> (8 * i)) & 0xFF;
|
||||
counts[(int)bucket]++;
|
||||
}
|
||||
|
||||
for (var j = 1; j < 256; j++)
|
||||
{
|
||||
counts[j] += counts[j - 1];
|
||||
}
|
||||
|
||||
for (var j = n - 1; j >= 0; j--)
|
||||
{
|
||||
var key = keys[currentOffset + j];
|
||||
var bucket = (key >> (8 * i)) & 0xFF;
|
||||
var newIndex = counts[(int)bucket] - 1;
|
||||
counts[(int)bucket]--;
|
||||
keys[nextOffset + newIndex] = key;
|
||||
indices[nextOffset + newIndex] = indices[currentOffset + j];
|
||||
}
|
||||
}
|
||||
|
||||
counts.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7d809dd521d214310bc148d1dc02f98f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UnityEngine.Rendering.Universal
|
||||
{
|
||||
[BurstCompile]
|
||||
struct ReorderJob<T> : IJobFor
|
||||
where T : struct
|
||||
{
|
||||
[ReadOnly]
|
||||
public NativeArray<int> indices;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<T> input;
|
||||
|
||||
[NativeDisableParallelForRestriction]
|
||||
public NativeArray<T> output;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var newIndex = indices[index];
|
||||
output[newIndex] = input[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ff96ea8778cf84d659b1bd2c721e4819
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UnityEngine.Rendering.Universal
|
||||
{
|
||||
[BurstCompile]
|
||||
unsafe struct SliceCombineJob : IJobFor
|
||||
{
|
||||
public int2 tileResolution;
|
||||
|
||||
public int wordsPerTile;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<uint> sliceLightMasksH;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<uint> sliceLightMasksV;
|
||||
|
||||
[NativeDisableParallelForRestriction]
|
||||
public NativeArray<uint> lightMasks;
|
||||
|
||||
public void Execute(int idY)
|
||||
{
|
||||
var baseIndexH = idY * wordsPerTile;
|
||||
var baseIndexRow = baseIndexH * tileResolution.x;
|
||||
for (var idX = 0; idX < tileResolution.x; idX++)
|
||||
{
|
||||
var baseIndexV = idX * wordsPerTile;
|
||||
var baseIndexTile = baseIndexRow + baseIndexV;
|
||||
for (var wordIndex = 0; wordIndex < wordsPerTile; wordIndex++)
|
||||
{
|
||||
lightMasks[baseIndexTile + wordIndex] = sliceLightMasksH[baseIndexH + wordIndex] & sliceLightMasksV[baseIndexV + wordIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5df5478e52f204fdea0fbfc8ab3d22de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UnityEngine.Rendering.Universal
|
||||
{
|
||||
// Culls slices along one axis of the screen.
|
||||
[BurstCompile]
|
||||
unsafe struct SliceCullingJob : IJobFor
|
||||
{
|
||||
public float scale;
|
||||
public float3 viewOrigin;
|
||||
public float3 viewForward;
|
||||
public float3 viewRight;
|
||||
public float3 viewUp;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<LightType> lightTypes;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<float> radiuses;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<float3> directions;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<float3> positions;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<float> coneRadiuses;
|
||||
|
||||
public int lightsPerTile;
|
||||
|
||||
[NativeDisableParallelForRestriction]
|
||||
public NativeArray<uint> sliceLightMasks;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var leftX = (((float)index) * scale) * 2f - 1f;
|
||||
var rightX = (((float)index + 1f) * scale) * 2f - 1f;
|
||||
var leftPlane = ComputePlane(viewOrigin,
|
||||
viewOrigin + viewForward + viewRight * leftX + viewUp,
|
||||
viewOrigin + viewForward + viewRight * leftX - viewUp);
|
||||
var rightPlane = ComputePlane(viewOrigin,
|
||||
viewOrigin + viewForward + viewRight * rightX - viewUp,
|
||||
viewOrigin + viewForward + viewRight * rightX + viewUp);
|
||||
|
||||
var lightCount = lightTypes.Length;
|
||||
var lightWordCount = (lightCount + 31) / 32;
|
||||
|
||||
var sectionOffset = index * lightsPerTile / 32;
|
||||
|
||||
// Handle lights in multiples of 32
|
||||
for (var lightWordIndex = 0; lightWordIndex < lightWordCount; lightWordIndex++)
|
||||
{
|
||||
var wordLightMask = 0u;
|
||||
var lightsInWord = math.min(32, lightCount - lightWordIndex * 32);
|
||||
for (var bitIndex = 0; bitIndex < lightsInWord; bitIndex++)
|
||||
{
|
||||
var lightIndex = lightWordIndex * 32 + bitIndex;
|
||||
if (ContainsLight(leftPlane, rightPlane, lightIndex))
|
||||
{
|
||||
wordLightMask |= 1u << bitIndex;
|
||||
}
|
||||
}
|
||||
|
||||
var wordIndex = sectionOffset + lightWordIndex;
|
||||
sliceLightMasks[wordIndex] = sliceLightMasks[wordIndex] | wordLightMask;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
bool ContainsLight(Plane leftPlane, Plane rightPlane, int lightIndex)
|
||||
{
|
||||
var hit = true;
|
||||
|
||||
var sphere = new Sphere
|
||||
{
|
||||
center = positions[lightIndex],
|
||||
radius = radiuses[lightIndex]
|
||||
};
|
||||
|
||||
if (SphereBehindPlane(sphere, leftPlane) || SphereBehindPlane(sphere, rightPlane))
|
||||
{
|
||||
hit = false;
|
||||
}
|
||||
|
||||
if (hit && lightTypes[lightIndex] == LightType.Spot)
|
||||
{
|
||||
var cone = new Cone
|
||||
{
|
||||
tip = sphere.center,
|
||||
direction = directions[lightIndex],
|
||||
height = radiuses[lightIndex],
|
||||
radius = coneRadiuses[lightIndex]
|
||||
};
|
||||
if (ConeBehindPlane(cone, leftPlane) || ConeBehindPlane(cone, rightPlane))
|
||||
{
|
||||
hit = false;
|
||||
}
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
struct Cone
|
||||
{
|
||||
public float3 tip;
|
||||
public float3 direction;
|
||||
public float height;
|
||||
public float radius;
|
||||
}
|
||||
|
||||
struct Sphere
|
||||
{
|
||||
public float3 center;
|
||||
public float radius;
|
||||
}
|
||||
|
||||
struct Plane
|
||||
{
|
||||
public float3 normal;
|
||||
public float distanceToOrigin;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static Plane ComputePlane(float3 p0, float3 p1, float3 p2)
|
||||
{
|
||||
Plane plane;
|
||||
|
||||
float3 v0 = p1 - p0;
|
||||
float3 v2 = p2 - p0;
|
||||
|
||||
plane.normal = math.normalize(math.cross(v0, v2));
|
||||
|
||||
// Compute the distance to the origin using p0.
|
||||
plane.distanceToOrigin = math.dot(plane.normal, p0);
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static bool SphereBehindPlane(Sphere sphere, Plane plane)
|
||||
{
|
||||
float dist = math.dot(sphere.center, plane.normal) - plane.distanceToOrigin;
|
||||
return dist < -sphere.radius;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static bool PointBehindPlane(float3 p, Plane plane)
|
||||
{
|
||||
return math.dot(plane.normal, p) - plane.distanceToOrigin < 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static bool ConeBehindPlane(Cone cone, Plane plane)
|
||||
{
|
||||
float3 furthestPointDirection = math.cross(math.cross(plane.normal, cone.direction), cone.direction);
|
||||
float3 furthestPointOnCircle = cone.tip + cone.direction * cone.height - furthestPointDirection * cone.radius;
|
||||
return PointBehindPlane(cone.tip, plane) && PointBehindPlane(furthestPointOnCircle, plane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc45902ab38cd4ebe8e33c7792204ded
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
namespace UnityEngine.Rendering.Universal
|
||||
{
|
||||
internal enum TileSize
|
||||
{
|
||||
_8 = 8,
|
||||
_16 = 16,
|
||||
_32 = 32,
|
||||
_64 = 64
|
||||
}
|
||||
|
||||
static class TileSizeExtensions
|
||||
{
|
||||
public static bool IsValid(this TileSize tileSize)
|
||||
{
|
||||
return tileSize == TileSize._8 || tileSize == TileSize._16 || tileSize == TileSize._32 || tileSize == TileSize._64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c7b4abc88bafe43ecb5380692ea7e4fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace UnityEngine.Rendering.Universal
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct ZBin
|
||||
{
|
||||
public ushort minIndex;
|
||||
public ushort maxIndex;
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
unsafe struct ZBinningJob : IJobFor
|
||||
{
|
||||
// Do not use this for the innerloopBatchCount (use 1 for that). Use for dividing the arrayLength when scheduling.
|
||||
public const int batchCount = 64;
|
||||
|
||||
[NativeDisableParallelForRestriction]
|
||||
public NativeArray<ZBin> bins;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<LightMinMaxZ> minMaxZs;
|
||||
|
||||
public int binOffset;
|
||||
|
||||
public float zFactor;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var binsStart = batchCount * index;
|
||||
var binsEnd = math.min(binsStart + batchCount, bins.Length) - 1;
|
||||
|
||||
for (var i = binsStart; i <= binsEnd; i++)
|
||||
{
|
||||
bins[i] = new ZBin { minIndex = ushort.MaxValue, maxIndex = ushort.MaxValue };
|
||||
}
|
||||
|
||||
for (var lightIndex = 0; lightIndex < minMaxZs.Length; lightIndex++)
|
||||
{
|
||||
var ushortLightIndex = (ushort)lightIndex;
|
||||
var minMax = minMaxZs[lightIndex];
|
||||
var minBin = math.max((int)(math.sqrt(minMax.minZ) * zFactor) - binOffset, binsStart);
|
||||
var maxBin = math.min((int)(math.sqrt(minMax.maxZ) * zFactor) - binOffset, binsEnd);
|
||||
|
||||
for (var binIndex = minBin; binIndex <= maxBin; binIndex++)
|
||||
{
|
||||
var bin = bins[binIndex];
|
||||
bin.minIndex = Math.Min(bin.minIndex, ushortLightIndex);
|
||||
// This will always be the largest light index this bin has seen due to light iteration order.
|
||||
bin.maxIndex = ushortLightIndex;
|
||||
bins[binIndex] = bin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0ddf10b9a46e641ae8ba73c89b46512c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Add table
Add a link
Reference in a new issue