private unsafe bool FrustumCull(ref Cluster.GpuCluster cluster, ref CBMeshBatch cbMesh) { Vector3 position = cluster.BoundCenter; Vector3 extent = cluster.BoundExtent; Vector3 minPos = position - extent; Vector3 maxPos = position + extent; if (cbMesh.GpuDrivenFrustumMinPoint.X > maxPos.X || cbMesh.GpuDrivenFrustumMinPoint.Y > maxPos.Y || cbMesh.GpuDrivenFrustumMinPoint.Z > maxPos.Z) { return(true); } if (cbMesh.GpuDrivenFrustumMaxPoint.X < minPos.X || cbMesh.GpuDrivenFrustumMaxPoint.Y < minPos.Y || cbMesh.GpuDrivenFrustumMaxPoint.Z < minPos.Z) { return(true); } fixed(CBMeshBatch *pCBuffer = &cbMesh) { Vector4 *planes = (Vector4 *)pCBuffer; Vector3 absNormal = new Vector3(); for (uint i = 0; i < 6; ++i) { absNormal.X = (planes->X > 0) ? (planes->X) : (-planes->X); absNormal.Y = (planes->Y > 0) ? (planes->Y) : (-planes->Y); absNormal.Z = (planes->Z > 0) ? (planes->Z) : (-planes->Z); Vector3 *planeNormal = (Vector3 *)planes; float dist = Vector3.Dot(position, *planeNormal) + planes->W; float df = Vector3.Dot(absNormal, extent); if (dist - df > 0) { return(true); } planes++; } } return(false); }
private unsafe void UpdateIndexBufferCPU(CCommandList cmd, Graphics.CGfxCamera Camera) { if (mCpuDrawIndexBuffer == null) { return; } CBMeshBatch cbMesh = new CBMeshBatch(); { var pPlanes = stackalloc Plane[6]; Camera.CullingFrustum.GetPlanes(pPlanes); CBMeshBatch *pCBuffer = &cbMesh; Plane * planesTar = (Plane *)pCBuffer; for (uint i = 0; i < 6; i++) { planesTar[i] = pPlanes[i]; } cbMesh.GpuDrivenCameraPosition = Camera.CullingFrustum.TipPos; BoundingBox box = new BoundingBox(); Camera.CullingFrustum.GetBoundBox(ref box); cbMesh.GpuDrivenFrustumMinPoint = box.Minimum; cbMesh.GpuDrivenFrustumMaxPoint = box.Maximum; cbMesh.MeshBatchVertexStride = (uint)AllVertices.Count; cbMesh.ClusterNumber = (uint)GpuClusters.Count; UpdateCBMeshbatch(cmd, Camera); } UInt32_3 tri = new UInt32_3(); mDrawIndices.Clear(); for (int i = 0; i < GpuClusters.Count; i++) { var cluster = GpuClusters[i]; var GpuDrivenCameraDirection = GpuClusters[i].BoundCenter - cbMesh.GpuDrivenCameraPosition; var cameraDirInBoundSpace = Vector3.TransposeTransformNormal(GpuDrivenCameraDirection, GpuInstanceDatas[(int)cluster.InstanceId].InvMatrix); if (FrustumCull(ref cluster, ref cbMesh) == false) { UInt64 visBits = 0; if (cameraDirInBoundSpace.X >= 0) { visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_NX]; } else { visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_X]; } if (cameraDirInBoundSpace.Y >= 0) { visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_NY]; } else { visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_Y]; } if (cameraDirInBoundSpace.Z >= 0) { visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_NZ]; } else { visBits |= cluster.CubeFaces[(int)Cluster.GpuCluster.ECubeFace.CubeFace_Z]; } uint InstanceStartIndex = cbMesh.MeshBatchVertexStride * cluster.InstanceId; for (int j = 0; j < cluster.FaceCount; j++) { if (TestBit(visBits, j) == false) { continue; } int srcIndex = (int)(cluster.StartFaceIndex + j) * 3; tri.x = InstanceStartIndex + AllIndices[srcIndex]; tri.y = InstanceStartIndex + AllIndices[srcIndex + 1]; tri.z = InstanceStartIndex + AllIndices[srcIndex + 2]; mDrawIndices.Add(tri); } } } mDrawArgs.InstanceCount = 1; mDrawArgs.IndexCountPerInstance = (uint)mDrawIndices.Count * 3; uint size = (uint)(mDrawIndices.Count * sizeof(UInt32_3)); if (mCpuDrawIndexBuffer.Desc.ByteWidth > size) { mCpuDrawIndexBuffer.UpdateBuffData(cmd, mDrawIndices.GetBufferPtr(), size); } }