浏览代码

Add a Frustum struct

/main
Evgenii Golubev 7 年前
当前提交
521d4a50
共有 3 个文件被更改,包括 63 次插入41 次删除
  1. 70
      ScriptableRenderPipeline/Core/CoreRP/GeometryUtils.cs
  2. 32
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs
  3. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs

70
ScriptableRenderPipeline/Core/CoreRP/GeometryUtils.cs


}
}
public struct Frustum
{
public Plane[] planes; // Left, right, top, bottom, near, far
public Vector3[] corners; // Positions of the 8 corners
// The frustum will be camera-relative if given a camera-relative VP matrix.
public static Frustum Create(Matrix4x4 viewProjMatrix, bool depth_0_1, bool reverseZ)
{
Frustum frustum = new Frustum();
frustum.planes = new Plane[6];
frustum.corners = new Vector3[8];
GeometryUtility.CalculateFrustumPlanes(viewProjMatrix, frustum.planes);
if (depth_0_1)
{
// See "Fast Extraction of Viewing Frustum Planes" by Gribb and Hartmann.
Vector3 nv = new Vector3(viewProjMatrix.m20, viewProjMatrix.m21, viewProjMatrix.m22);
Plane np = new Plane(nv / nv.magnitude, viewProjMatrix.m23 / nv.magnitude);
frustum.planes[4] = np;
}
if (reverseZ)
{
Plane tmp = frustum.planes[4];
frustum.planes[4] = frustum.planes[5];
frustum.planes[5] = tmp;
}
Matrix4x4 invViewProjMatrix = viewProjMatrix.inverse;
// Unproject 8 frustum points.
frustum.corners[0] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, -1, 1));
frustum.corners[1] = invViewProjMatrix.MultiplyPoint(new Vector3( 1, -1, 1));
frustum.corners[2] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, 1, 1));
frustum.corners[3] = invViewProjMatrix.MultiplyPoint(new Vector3( 1, 1, 1));
frustum.corners[4] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, -1, 0));
frustum.corners[5] = invViewProjMatrix.MultiplyPoint(new Vector3( 1, -1, 0));
frustum.corners[6] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, 1, 0));
frustum.corners[7] = invViewProjMatrix.MultiplyPoint(new Vector3( 1, 1, 0));
return frustum;
}
}
Vector3 center;
Vector3 right, up, forward; // X, Y, Z, normalized
Vector3 extents; // Size of the half-diagonal
public Vector3 center;
public Vector3 right, up, forward; // X, Y, Z, normalized
public Vector3 extents; // Size of the half-diagonal
public static OrientedBBox Create(Transform t)
{

}
// 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)
// 'cameraRelativeOffset' can be used to intersect a world-space OBB with a camera-relative frustum.
public bool OverlapsFrustum(Frustum frustum, int numPlanes, int numCorners, Vector3 cameraRelativeOffset)
{
Vector3 relCenter = center + cameraRelativeOffset;

// 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++)
for (int i = 0; overlap && i < numPlanes; i++)
Vector3 n = frustumPlanes[i].normal;
float d = frustumPlanes[i].distance;
Vector3 n = frustum.planes[i].normal;
float d = frustum.planes[i].distance;
// Max projection of the half-diagonal onto the normal (always positive).
float maxHalfDiagProj = extents.x * Mathf.Abs(Vector3.Dot(n, right))

planes[2].normal = forward;
planes[2].distance = extents.z;
for (int i = 0; overlap && (i < 3); i++)
for (int i = 0; overlap && i < 3; i++)
{
Plane plane = planes[i];

// Merge 2 loops. Continue as long as all points are outside either plane.
for (int j = 0; (outsidePos || outsideNeg) && (j < numCorners); j++)
for (int j = 0; j < numCorners; j++)
float proj = Vector3.Dot(plane.normal, frustumCorners[j] - relCenter);
float proj = Vector3.Dot(plane.normal, frustum.corners[j] - relCenter);
outsidePos = outsidePos && ( proj > plane.distance);
outsideNeg = outsideNeg && (-proj > plane.distance);
}

32
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs


public Matrix4x4 projMatrix;
public Matrix4x4 nonJitteredProjMatrix;
public Vector4 screenSize;
public Plane[] frustumPlanes;
public Frustum frustum;
public Vector3[] frustumCorners;
public Camera camera;
public uint taaFrameIndex;
public Vector2 taaFrameRotation;

{
camera = cam;
m_AdditionalCameraData = cam.GetComponent<HDAdditionalCameraData>();
frustumPlanes = new Plane[6];
frustum = new Frustum();
frustumCorners = new Vector3[8];
postprocessRenderContext = new PostProcessRenderContext();
Reset();
}

prevViewProjMatrix *= cameraDisplacement; // Now prevViewProjMatrix correctly transforms this frame's camera-relative positionWS
}
// Warning: near and far planes appear to be broken (or rather far plane seems broken)
// Also note: frustum plane normals are inward-facing.
GeometryUtility.CalculateFrustumPlanes(viewProjMatrix, frustumPlanes);
Vector3 forward = -viewMatrix.GetRow(2); // camera.forward is not always available
// Near, far.
frustumPlanes[4].normal = forward;
frustumPlanes[4].distance = -Vector3.Dot(forward, relPos) - camera.nearClipPlane;
frustumPlanes[5].normal = -forward;
frustumPlanes[5].distance = Vector3.Dot(forward, relPos) + camera.farClipPlane;
frustum = Frustum.Create(viewProjMatrix, true, true);
frustumPlaneEquations[i] = new Vector4(frustumPlanes[i].normal.x, frustumPlanes[i].normal.y, frustumPlanes[i].normal.z, frustumPlanes[i].distance);
frustumPlaneEquations[i] = new Vector4(frustum.planes[i].normal.x, frustum.planes[i].normal.y, frustum.planes[i].normal.z, frustum.planes[i].distance);
Matrix4x4 invViewProjMatrix = viewProjMatrix.inverse;
// Unproject 8 frustum points.
frustumCorners[0] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, -1, 1));
frustumCorners[1] = invViewProjMatrix.MultiplyPoint(new Vector3( 1, -1, 1));
frustumCorners[2] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, 1, 1));
frustumCorners[3] = invViewProjMatrix.MultiplyPoint(new Vector3( 1, 1, 1));
frustumCorners[4] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, -1, 0));
frustumCorners[5] = invViewProjMatrix.MultiplyPoint(new Vector3( 1, -1, 0));
frustumCorners[6] = invViewProjMatrix.MultiplyPoint(new Vector3(-1, 1, 0));
frustumCorners[7] = invViewProjMatrix.MultiplyPoint(new Vector3( 1, 1, 0));
m_LastFrameActive = Time.frameCount;

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


var obb = OrientedBBox.Create(fogComponent.transform);
// Frustum cull on the CPU for now. TODO: do it on the GPU.
if (!obb.OverlapsFrustum(camera.frustumPlanes, 6, camera.frustumCorners, 8, camOffset))
if (!obb.OverlapsFrustum(camera.frustum, 6, 8, camOffset))
{
Debug.Log("Culled.");
}

正在加载...
取消
保存