浏览代码

Move the OrientedBBox code

/main
Evgenii Golubev 7 年前
当前提交
2b155faa
共有 2 个文件被更改,包括 92 次插入93 次删除
  1. 89
      ScriptableRenderPipeline/Core/CoreRP/GeometryUtils.cs
  2. 96
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs

89
ScriptableRenderPipeline/Core/CoreRP/GeometryUtils.cs


return Matrix4x4.Perspective(camera.fieldOfView, camera.aspect, camera.nearClipPlane, camera.farClipPlane);
}
}
public struct OrientedBBox
{
// TODO: in the shader, merge axes and extents, and 16-byte align the data structure.
Vector3 center;
Vector3 right, up, forward; // X, Y, Z, normalized
Vector3 extents; // Size of the half-diagonal
public static OrientedBBox Create(Transform t)
{
OrientedBBox obb = new OrientedBBox();
obb.center = t.position;
obb.right = t.right;
obb.up = t.up;
obb.forward = t.forward;
obb.extents = t.localScale * 0.5f;
return obb;
}
// Returns 'true' if the OBB intersects (or is inside) the frustum, 'false' otherwise.
public bool OverlapsFrustum(Plane[] frustumPlanes, int numPlanes,
Vector3[] frustumCorners, int numCorners,
Vector3 cameraRelativeOffset)
{
Vector3 relCenter = center + cameraRelativeOffset;
bool overlap = true;
// Test the OBB against frustum planes. Frustum planes have inward-facing.
// The OBB is outside if it's entirely behind one of the frustum planes.
// See "Real-Time Rendering", 3rd Edition, 16.10.2.
for (int i = 0; overlap && (i < numPlanes); i++)
{
Vector3 n = frustumPlanes[i].normal;
float d = frustumPlanes[i].distance;
// Max projection of the half-diagonal onto the normal (always positive).
float maxHalfDiagProj = extents.x * Mathf.Abs(Vector3.Dot(n, right))
+ extents.y * Mathf.Abs(Vector3.Dot(n, up))
+ extents.z * Mathf.Abs(Vector3.Dot(n, forward));
// Negative distance -> center behind the plane (outside).
float centerToPlaneDist = Vector3.Dot(n, relCenter) + d;
// outside = maxHalfDiagProj < -centerToPlaneDist
// outside = maxHalfDiagProj + centerToPlaneDist < 0
// overlap = overlap && !outside
overlap = overlap && (maxHalfDiagProj + centerToPlaneDist >= 0);
}
if (numCorners == 0) return overlap;
// Test the frustum corners against OBB planes. The OBB planes are outward-facing.
// The frustum is outside if all of its corners are entirely in front of one of the OBB planes.
// See "Correct Frustum Culling" by Inigo Quilez.
// We can exploit the symmetry of the box by only testing against 3 planes rather than 6.
Plane[] planes = new Plane[3];
planes[0].normal = right;
planes[0].distance = extents.x;
planes[1].normal = up;
planes[1].distance = extents.y;
planes[2].normal = forward;
planes[2].distance = extents.z;
for (int i = 0; overlap && (i < 3); i++)
{
Plane plane = planes[i];
// We need a separate counter for the "box fully inside frustum" case.
bool outsidePos = true; // Positive normal
bool outsideNeg = true; // Reversed normal
// Merge 2 loops. Continue as long as all points are outside either plane.
for (int j = 0; (outsidePos || outsideNeg) && (j < numCorners); j++)
{
float proj = Vector3.Dot(plane.normal, frustumCorners[j] - relCenter);
outsidePos = outsidePos && ( proj > plane.distance);
outsideNeg = outsideNeg && (-proj > plane.distance);
}
overlap = overlap && !(outsidePos || outsideNeg);
}
return overlap;
}
} // struct OrientedBBox
}

96
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs


cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, vBuffer.GetLightingIntegralBuffer());
}
struct OrientedBBox
{
// TODO: in the shader, merge axes and extents, and 16-byte align the data structure.
Vector3 center;
Vector3 right, up, forward; // X, Y, Z, normalized
Vector3 extents; // Size of the half-diagonal
public static OrientedBBox Create(Transform t)
{
return Create(t, Vector3.zero);
}
public static OrientedBBox Create(Transform t, Vector3 offset)
{
OrientedBBox obb = new OrientedBBox();
obb.center = t.position + offset;
obb.right = t.right;
obb.up = t.up;
obb.forward = t.forward;
obb.extents = t.localScale * 0.5f;
return obb;
}
// Returns 'true' if the OBB intersects (or is inside) the frustum, 'false' otherwise.
public bool OverlapsFrustum(Plane[] frustumPlanes, int numPlanes,
Vector3[] frustumCorners, int numCorners)
{
bool overlap = true;
// Test the OBB against frustum planes. Frustum planes have inward-facing.
// The OBB is outside if it's entirely behind one of the frustum planes.
// See "Real-Time Rendering", 3rd Edition, 16.10.2.
for (int i = 0; overlap && (i < numPlanes); i++)
{
Vector3 n = frustumPlanes[i].normal;
float d = frustumPlanes[i].distance;
// Max projection of the half-diagonal onto the normal (always positive).
float maxHalfDiagProj = extents.x * Mathf.Abs(Vector3.Dot(n, right))
+ extents.y * Mathf.Abs(Vector3.Dot(n, up))
+ extents.z * Mathf.Abs(Vector3.Dot(n, forward));
// Negative distance -> center behind the plane (outside).
float centerToPlaneDist = Vector3.Dot(n, center) + d;
// outside = maxHalfDiagProj < -centerToPlaneDist
// outside = maxHalfDiagProj + centerToPlaneDist < 0
// overlap = overlap && !outside
overlap = overlap && (maxHalfDiagProj + centerToPlaneDist >= 0);
}
if (numCorners == 0) return overlap;
// Test the frustum corners against OBB planes. The OBB planes are outward-facing.
// The frustum is outside if all of its corners are entirely in front of one of the OBB planes.
// See "Correct Frustum Culling" by Inigo Quilez.
// We can exploit the symmetry of the box by only testing against 3 planes rather than 6.
Plane[] planes = new Plane[3];
planes[0].normal = right;
planes[0].distance = extents.x;
planes[1].normal = up;
planes[1].distance = extents.y;
planes[2].normal = forward;
planes[2].distance = extents.z;
for (int i = 0; overlap && (i < 3); i++)
{
Plane plane = planes[i];
// We need a separate counter for the "box fully inside frustum" case.
bool outsidePos = true; // Positive normal
bool outsideNeg = true; // Reversed normal
// Merge 2 loops. Continue as long as all points are outside either plane.
for (int j = 0; (outsidePos || outsideNeg) && (j < numCorners); j++)
{
float proj = Vector3.Dot(plane.normal, frustumCorners[j] - center);
outsidePos = outsidePos && ( proj > plane.distance);
outsideNeg = outsideNeg && (-proj > plane.distance);
}
overlap = overlap && !(outsidePos || outsideNeg);
}
return overlap;
}
}
if (preset == VolumetricLightingPreset.Off) return;
if (camera.camera.cameraType != CameraType.SceneView) return;
Vector3 camPosition = camera.camera.transform.position;

{
// Convert to the camera-relative coordinates if necessary.
// TODO: cache these?
var obb = OrientedBBox.Create(fogComponent.transform, camOffset);
var obb = OrientedBBox.Create(fogComponent.transform);
if (!obb.OverlapsFrustum(camera.frustumPlanes, 6, camera.frustumCorners, 8))
if (!obb.OverlapsFrustum(camera.frustumPlanes, 6, camera.frustumCorners, 8, camOffset))
{
Debug.Log("Culled.");
}

正在加载...
取消
保存