Compare commits
1 Commits
master
...
3e84fe2281
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e84fe2281 |
@@ -2,7 +2,9 @@ using Misaki.AoVolume;
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Misaki.AoVolume.Shader;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Experimental.Rendering;
|
||||
using UnityEngine.Rendering;
|
||||
@@ -11,6 +13,7 @@ using UnityEngine.Rendering.HighDefinition;
|
||||
internal class AoVolumePass : CustomPass
|
||||
{
|
||||
private NativeArray<OrientedBoundingBox> _volumeBounds;
|
||||
private NativeList<VolumeData> _culledVolumeDatas;
|
||||
private ComputeBuffer _volumeBoundsBuffer;
|
||||
private ComputeBuffer _visibleIndicesBuffer;
|
||||
private ComputeBuffer _visibleVolumeCountBuffer;
|
||||
@@ -42,6 +45,7 @@ internal class AoVolumePass : CustomPass
|
||||
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
|
||||
{
|
||||
_volumeBounds = new NativeArray<OrientedBoundingBox>(maxVolumeOnScreen, Allocator.Persistent);
|
||||
_culledVolumeDatas = new NativeList<VolumeData>(maxVolumeOnScreen, Allocator.Persistent);
|
||||
_volumeBoundsBuffer = new ComputeBuffer(maxVolumeOnScreen, Marshal.SizeOf<OrientedBoundingBox>());
|
||||
_visibleIndicesBuffer = new ComputeBuffer(maxVolumeOnScreen, Marshal.SizeOf<uint>(), ComputeBufferType.Raw);
|
||||
_visibleVolumeCountBuffer = new ComputeBuffer(1, Marshal.SizeOf<uint>(), ComputeBufferType.Counter);
|
||||
@@ -58,13 +62,50 @@ internal class AoVolumePass : CustomPass
|
||||
{
|
||||
return Mathf.FloorToInt(Mathf.Log(Mathf.Min(hDCamera.actualWidth, hDCamera.actualHeight), 2)) - 1;
|
||||
}
|
||||
private void FrustumCulling(CustomPassContext ctx, ref int volumeCount)
|
||||
{
|
||||
Frustum cameraFrustum = ctx.hdCamera.frustum;
|
||||
|
||||
GPUFrustum frustum = new()
|
||||
{
|
||||
normal0 = cameraFrustum.planes[0].normal,
|
||||
dist0 = cameraFrustum.planes[0].distance,
|
||||
normal1 = cameraFrustum.planes[1].normal,
|
||||
dist1 = cameraFrustum.planes[1].distance,
|
||||
normal2 = cameraFrustum.planes[2].normal,
|
||||
dist2 = cameraFrustum.planes[2].distance,
|
||||
normal3 = cameraFrustum.planes[3].normal,
|
||||
dist3 = cameraFrustum.planes[3].distance,
|
||||
normal4 = cameraFrustum.planes[4].normal,
|
||||
dist4 = cameraFrustum.planes[4].distance,
|
||||
normal5 = cameraFrustum.planes[5].normal,
|
||||
dist5 = cameraFrustum.planes[5].distance,
|
||||
corner0 = cameraFrustum.corners[0],
|
||||
corner1 = cameraFrustum.corners[1],
|
||||
corner2 = cameraFrustum.corners[2],
|
||||
corner3 = cameraFrustum.corners[3],
|
||||
corner4 = cameraFrustum.corners[4],
|
||||
corner5 = cameraFrustum.corners[5],
|
||||
corner6 = cameraFrustum.corners[6],
|
||||
corner7 = cameraFrustum.corners[7],
|
||||
};
|
||||
|
||||
_culledVolumeDatas.Clear();
|
||||
FrustumCullingJob cullingJob = new()
|
||||
{
|
||||
GPUFrustum = frustum,
|
||||
InputVolumeDatas = VolumeDatabase.Instance.VolumeDatas,
|
||||
InputVolumeBounds = _volumeBounds,
|
||||
OutputVolumeDataWriter = _culledVolumeDatas.AsParallelWriter()
|
||||
};
|
||||
|
||||
JobHandle cullingJobHandle = cullingJob.Schedule(volumeCount, 64);
|
||||
cullingJobHandle.Complete();
|
||||
volumeCount = _culledVolumeDatas.Length;
|
||||
}
|
||||
|
||||
private void HierarchicalZCulling(CustomPassContext ctx, int volumeCount)
|
||||
{
|
||||
for (var i = 0; i < volumeCount; i++)
|
||||
{
|
||||
_volumeBounds[i] = new OrientedBoundingBox(VolumeDatabase.Instance.VolumeDatas[i].worldMatrix);
|
||||
}
|
||||
_volumeBoundsBuffer.SetData(_volumeBounds);
|
||||
|
||||
ctx.cmd.SetComputeBufferParam(cullingShader, 0, "_VolumeBounds", _volumeBoundsBuffer);
|
||||
@@ -81,7 +122,7 @@ internal class AoVolumePass : CustomPass
|
||||
|
||||
private void RenderVisibleVolumes(CustomPassContext ctx)
|
||||
{
|
||||
_volumeDataBuffer.SetData(VolumeDatabase.Instance.VolumeDatas);
|
||||
_volumeDataBuffer.SetData(_culledVolumeDatas.AsArray());
|
||||
|
||||
ctx.cmd.SetComputeBufferParam(renderingShader, 0, "_VolumeDatas", _volumeDataBuffer);
|
||||
ctx.cmd.SetComputeBufferParam(renderingShader, 0, "_VisibleVolumeCount", _visibleVolumeCountBuffer);
|
||||
@@ -140,6 +181,7 @@ internal class AoVolumePass : CustomPass
|
||||
return;
|
||||
}
|
||||
|
||||
FrustumCulling(ctx, ref volumeCount);
|
||||
HierarchicalZCulling(ctx, volumeCount);
|
||||
RenderVisibleVolumes(ctx);
|
||||
//DebugVisibleVolumes();
|
||||
@@ -149,6 +191,7 @@ internal class AoVolumePass : CustomPass
|
||||
protected override void Cleanup()
|
||||
{
|
||||
_volumeBounds.Dispose();
|
||||
_culledVolumeDatas.Dispose();
|
||||
_volumeBoundsBuffer?.Dispose();
|
||||
_visibleIndicesBuffer?.Dispose();
|
||||
_visibleVolumeCountBuffer?.Dispose();
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"GUID:457756d89b35d2941b3e7b37b4ece6f1",
|
||||
"GUID:df380645f10b7bc4b97d4f5eb6303d95",
|
||||
"GUID:e0cd26848372d4e5c891c569017e11f1",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:2665a8d13d1b3f18800f46e256720795"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
124
Runtime/Shader/FrustumCullingJob.cs
Normal file
124
Runtime/Shader/FrustumCullingJob.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.AoVolume.Shader
|
||||
{
|
||||
[BurstCompile]
|
||||
internal struct FrustumCullingJob : IJobParallelFor
|
||||
{
|
||||
[ReadOnly] internal GPUFrustum GPUFrustum;
|
||||
[ReadOnly] internal NativeArray<VolumeData> InputVolumeDatas;
|
||||
internal NativeArray<OrientedBoundingBox> InputVolumeBounds;
|
||||
internal NativeList<VolumeData>.ParallelWriter OutputVolumeDataWriter;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
OrientedBoundingBox obb = new(InputVolumeDatas[index].worldMatrix);
|
||||
if (FrustumObbIntersection(obb))
|
||||
{
|
||||
OutputVolumeDataWriter.AddNoResize(InputVolumeDatas[index]);
|
||||
InputVolumeBounds[index] = obb;
|
||||
}
|
||||
}
|
||||
|
||||
private struct FrustumPlane
|
||||
{
|
||||
internal Vector3 Normal;
|
||||
internal float Distance;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool CheckOverlap(OrientedBoundingBox obb, Vector3 planeNormal, float planeDist)
|
||||
{
|
||||
float maxHalfDiagProj = obb.extent.x * Mathf.Abs(Vector3.Dot(obb.right, planeNormal)) +
|
||||
obb.extent.y * Mathf.Abs(Vector3.Dot(obb.up, planeNormal)) +
|
||||
obb.extent.z * Mathf.Abs(Vector3.Dot(GetForward(obb), planeNormal));
|
||||
float centerProj = Vector3.Dot(obb.center, planeNormal) + planeDist;
|
||||
return maxHalfDiagProj + centerProj >= 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector3 GetForward(OrientedBoundingBox obb)
|
||||
{
|
||||
return Vector3.Cross(obb.up, obb.right);
|
||||
}
|
||||
|
||||
private bool FrustumObbIntersection(OrientedBoundingBox obb)
|
||||
{
|
||||
bool overlap = CheckOverlap(obb, GPUFrustum.normal0, GPUFrustum.dist0);
|
||||
overlap &= CheckOverlap(obb, GPUFrustum.normal1, GPUFrustum.dist1);
|
||||
overlap &= CheckOverlap(obb, GPUFrustum.normal2, GPUFrustum.dist2);
|
||||
overlap &= CheckOverlap(obb, GPUFrustum.normal3, GPUFrustum.dist3);
|
||||
overlap &= CheckOverlap(obb, GPUFrustum.normal4, GPUFrustum.dist4);
|
||||
overlap &= CheckOverlap(obb, GPUFrustum.normal5, GPUFrustum.dist5);
|
||||
|
||||
var planes = new NativeArray<FrustumPlane>(3, Allocator.Temp);
|
||||
planes[0] = new FrustumPlane
|
||||
{
|
||||
Normal = obb.right,
|
||||
Distance = obb.extent.x
|
||||
};
|
||||
planes[1] = new FrustumPlane
|
||||
{
|
||||
Normal = obb.up,
|
||||
Distance = obb.extent.y
|
||||
};
|
||||
planes[2] = new FrustumPlane
|
||||
{
|
||||
Normal = GetForward(obb),
|
||||
Distance = obb.extent.z
|
||||
};
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
bool outsidePos = true;
|
||||
bool outsideNeg = true;
|
||||
|
||||
float proj = Vector3.Dot(planes[i].Normal, op_Subtraction(GPUFrustum.corner0, obb.center));
|
||||
outsidePos &= proj > planes[i].Distance;
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
|
||||
proj = Vector3.Dot(planes[i].Normal, op_Subtraction(GPUFrustum.corner1, obb.center));
|
||||
outsidePos &= proj > planes[i].Distance;
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
|
||||
proj = Vector3.Dot(planes[i].Normal, op_Subtraction(GPUFrustum.corner2, obb.center));
|
||||
outsidePos &= proj > planes[i].Distance;
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
|
||||
proj = Vector3.Dot(planes[i].Normal, op_Subtraction(GPUFrustum.corner3, obb.center));
|
||||
outsidePos &= proj > planes[i].Distance;
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
|
||||
proj = Vector3.Dot(planes[i].Normal, op_Subtraction(GPUFrustum.corner4, obb.center));
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
|
||||
proj = Vector3.Dot(planes[i].Normal, op_Subtraction(GPUFrustum.corner5, obb.center));
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
|
||||
proj = Vector3.Dot(planes[i].Normal, op_Subtraction(GPUFrustum.corner6, obb.center));
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
|
||||
proj = Vector3.Dot(planes[i].Normal, op_Subtraction(GPUFrustum.corner7, obb.center));
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
outsideNeg &= -proj > planes[i].Distance;
|
||||
|
||||
overlap &= !(outsidePos || outsideNeg);
|
||||
}
|
||||
|
||||
planes.Dispose();
|
||||
return overlap;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector3 op_Subtraction(Vector4 vector4, Vector3 vector3)
|
||||
{
|
||||
return new Vector3(vector4.x - vector3.x, vector4.y - vector3.y, vector4.z - vector3.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Shader/FrustumCullingJob.cs.meta
Normal file
3
Runtime/Shader/FrustumCullingJob.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5403ee0538c94d9abc5aa44a761092d0
|
||||
timeCreated: 1740495091
|
||||
Reference in New Issue
Block a user