Skip to content
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;

namespace Unity.Rendering
namespace Unity.Rendering.FrustumPlanes
{
public struct FrustumPlanes
{
Expand All @@ -14,77 +13,112 @@ public enum IntersectResult
Partial
};

static public void FromCamera(Camera camera, NativeArray<float4> planes)
public struct PlanePacket4
{
if (planes == null)
throw new ArgumentNullException("The argument planes cannot be null.");
if (planes.Length != 6)
throw new ArgumentException("The argument planes does not have the expected length 6.");
public float4 Xs;
public float4 Ys;
public float4 Zs;
public float4 Distances;
}

Plane[] sourcePlanes = GeometryUtility.CalculateFrustumPlanes(camera);
public static NativeArray<PlanePacket4> BuildSOAPlanePacketsMulti(NativeArray<Plane> cullingPlanes, NativeArray<int> splitCounts, Allocator allocator)
{
int totalPacketCount = 0;
for (int s = 0; s < splitCounts.Length; ++s)
{
totalPacketCount += (splitCounts[s] + 3) >> 2;
}

var cameraToWorld = camera.cameraToWorldMatrix;
var eyePos = cameraToWorld.MultiplyPoint(Vector3.zero);
var viewDir = new float3(cameraToWorld.m02, cameraToWorld.m12, cameraToWorld.m22);
viewDir = -math.normalizesafe(viewDir);
var planes = new NativeArray<PlanePacket4>(totalPacketCount, allocator, NativeArrayOptions.UninitializedMemory);

// Near Plane
sourcePlanes[4].SetNormalAndPosition(viewDir, eyePos);
sourcePlanes[4].distance -= camera.nearClipPlane;
int dstOffset = 0;
int srcOffset = 0;
for (int s = 0; s < splitCounts.Length; ++s)
{
int cullingPlaneCount = splitCounts[s];
int packetCount = (cullingPlaneCount + 3) >> 2;

// Far plane
sourcePlanes[5].SetNormalAndPosition(-viewDir, eyePos);
sourcePlanes[5].distance += camera.farClipPlane;
for (int i = 0; i < cullingPlaneCount; i++)
{
var p = planes[dstOffset + (i >> 2)];
p.Xs[i & 3] = cullingPlanes[srcOffset + i].normal.x;
p.Ys[i & 3] = cullingPlanes[srcOffset + i].normal.y;
p.Zs[i & 3] = cullingPlanes[srcOffset + i].normal.z;
p.Distances[i & 3] = cullingPlanes[srcOffset + i].distance;
planes[dstOffset + (i >> 2)] = p;
}

for (int i = 0; i < 6; ++i)
{
planes[i] = new float4(sourcePlanes[i].normal.x, sourcePlanes[i].normal.y, sourcePlanes[i].normal.z,
sourcePlanes[i].distance);
// Populate the remaining planes with values that are always "in"
for (int i = cullingPlaneCount; i < 4 * packetCount; ++i)
{
var p = planes[dstOffset + (i >> 2)];
p.Xs[i & 3] = 1.0f;
p.Ys[i & 3] = 0.0f;
p.Zs[i & 3] = 0.0f;

// This value was before hardcoded to 32786.0f.
// It was causing the culling system to discard the rendering of entities having a X coordinate approximately less than -32786.
// We could not find anything relying on this number, so the value has been increased to 1 billion
p.Distances[i & 3] = 1e9f;

planes[dstOffset + (i >> 2)] = p;
}

srcOffset += cullingPlaneCount;
dstOffset += packetCount;
}
return planes;
}

static public IntersectResult Intersect(NativeArray<float4> cullingPlanes, AABB a)
// Returns a bitmask (one 1 per split): 1 = visible, 0 = not visible in that split.
static public uint Intersect2NoPartialMulti(NativeArray<PlanePacket4> cullingPlanePackets, NativeArray<int> splitCounts, AABB a)
{
float3 m = a.Center;
float3 extent = a.Extents;
float4 mx = a.Center.xxxx;
float4 my = a.Center.yyyy;
float4 mz = a.Center.zzzz;

var inCount = 0;
for (int i = 0; i < cullingPlanes.Length; i++)
float4 ex = a.Extents.xxxx;
float4 ey = a.Extents.yyyy;
float4 ez = a.Extents.zzzz;

uint outMask = 0;

int offset = 0;
for (int s = 0; s < splitCounts.Length; ++s)
{
float3 normal = cullingPlanes[i].xyz;
float dist = math.dot(normal, m) + cullingPlanes[i].w;
float radius = math.dot(extent, math.abs(normal));
if (dist + radius <= 0)
return IntersectResult.Out;

if (dist > radius)
inCount++;
}
int packetCount = (splitCounts[s] + 3) >> 2;

return (inCount == cullingPlanes.Length) ? IntersectResult.In : IntersectResult.Partial;
}
int4 masks = 0;
for (int i = 0; i < packetCount; i++)
{
var p = cullingPlanePackets[offset + i];
float4 distances = dot4(p.Xs, p.Ys, p.Zs, mx, my, mz) + p.Distances;
float4 radii = dot4(ex, ey, ez, math.abs(p.Xs), math.abs(p.Ys), math.abs(p.Zs));
masks += (int4)(distances + radii <= 0);
}

public struct PlanePacket4
{
public float4 Xs;
public float4 Ys;
public float4 Zs;
public float4 Distances;
int outCount = math.csum(masks);
if (outCount == 0) outMask |= 1u << s;

offset += packetCount;
}

return outMask;
}

public static NativeArray<PlanePacket4> BuildSOAPlanePackets(NativeArray<Plane> cullingPlanes, Allocator allocator)
public static NativeArray<PlanePacket4> BuildSOAPlanePackets(NativeArray<Plane> cullingPlanes, int offset, int count, Allocator allocator)
{
int cullingPlaneCount = cullingPlanes.Length;
int cullingPlaneCount = count;
int packetCount = (cullingPlaneCount + 3) >> 2;
var planes = new NativeArray<PlanePacket4>(packetCount, allocator, NativeArrayOptions.UninitializedMemory);

for (int i = 0; i < cullingPlaneCount; i++)
{
var p = planes[i >> 2];
p.Xs[i & 3] = cullingPlanes[i].normal.x;
p.Ys[i & 3] = cullingPlanes[i].normal.y;
p.Zs[i & 3] = cullingPlanes[i].normal.z;
p.Distances[i & 3] = cullingPlanes[i].distance;
p.Xs[i & 3] = cullingPlanes[i + offset].normal.x;
p.Ys[i & 3] = cullingPlanes[i + offset].normal.y;
p.Zs[i & 3] = cullingPlanes[i + offset].normal.z;
p.Distances[i & 3] = cullingPlanes[i + offset].distance;
planes[i >> 2] = p;
}

Expand All @@ -107,38 +141,6 @@ public static NativeArray<PlanePacket4> BuildSOAPlanePackets(NativeArray<Plane>
return planes;
}

static public IntersectResult Intersect2(NativeArray<PlanePacket4> cullingPlanePackets, AABB a)
{
float4 mx = a.Center.xxxx;
float4 my = a.Center.yyyy;
float4 mz = a.Center.zzzz;

float4 ex = a.Extents.xxxx;
float4 ey = a.Extents.yyyy;
float4 ez = a.Extents.zzzz;

int4 outCounts = 0;
int4 inCounts = 0;

for (int i = 0; i < cullingPlanePackets.Length; i++)
{
var p = cullingPlanePackets[i];
float4 distances = dot4(p.Xs, p.Ys, p.Zs, mx, my, mz) + p.Distances;
float4 radii = dot4(ex, ey, ez, math.abs(p.Xs), math.abs(p.Ys), math.abs(p.Zs));

outCounts += (int4)(distances + radii < 0);
inCounts += (int4)(distances >= radii);
}

int inCount = math.csum(inCounts);
int outCount = math.csum(outCounts);

if (outCount != 0)
return IntersectResult.Out;
else
return (inCount == 4 * cullingPlanePackets.Length) ? IntersectResult.In : IntersectResult.Partial;
}

static public IntersectResult Intersect2NoPartial(NativeArray<PlanePacket4> cullingPlanePackets, AABB a)
{
float4 mx = a.Center.xxxx;
Expand Down Expand Up @@ -168,26 +170,5 @@ private static float4 dot4(float4 xs, float4 ys, float4 zs, float4 mx, float4 my
{
return xs * mx + ys * my + zs * mz;
}

static public IntersectResult Intersect(NativeArray<float4> planes, float3 center, float radius)
{
var inCount = 0;

for (int i = 0; i < planes.Length; i++)
{
var d = math.dot(planes[i].xyz, center) + planes[i].w;
if (d < -radius)
{
return IntersectResult.Out;
}

if (d > radius)
{
inCount++;
}
}

return (inCount == planes.Length) ? IntersectResult.In : IntersectResult.Partial;
}
}
}
Loading