#pragma warning restore 649 #endif public void ExecuteNext(LocalGroupKey internalBatchIndex, ref BatchChunkData chunkData) { #if UNITY_EDITOR Stats[ThreadIndex].Stats[CullingStats.kLodTotal]++; #endif var localIndex = internalBatchIndex.Value; var chunkInstanceCount = chunkData.ChunkInstanceCount; var isOrtho = LODParams.isOrtho; ChunkInstanceLodEnabled chunkEntityLodEnabled = chunkData.InstanceLodEnableds; #if UNITY_EDITOR ChunkInstanceLodEnabled oldEntityLodEnabled = chunkEntityLodEnabled; #endif var forceLowLOD = ForceLowLOD[localIndex]; if (0 == (chunkData.Flags & BatchChunkData.kFlagHasLodData)) { #if UNITY_EDITOR Stats[ThreadIndex].Stats[CullingStats.kLodNoRequirements]++; #endif chunkEntityLodEnabled.Enabled[0] = 0; chunkEntityLodEnabled.Enabled[1] = 0; chunkData.ForceLowLODPrevious = forceLowLOD; for (int i = 0; i < chunkInstanceCount; ++i) { int wordIndex = i >> 6; int bitIndex = i & 63; chunkEntityLodEnabled.Enabled[wordIndex] |= 1ul << bitIndex; } } else { int diff = (int)chunkData.MovementGraceFixed16 - CameraMoveDistanceFixed16; chunkData.MovementGraceFixed16 = (ushort)math.max(0, diff); var graceExpired = chunkData.MovementGraceFixed16 == 0; var forceLodChanged = forceLowLOD != chunkData.ForceLowLODPrevious; if (graceExpired || forceLodChanged || DistanceScaleChanged) { chunkEntityLodEnabled.Enabled[0] = 0; chunkEntityLodEnabled.Enabled[1] = 0; #if UNITY_EDITOR Stats[ThreadIndex].Stats[CullingStats.kLodChunksTested]++; #endif var chunk = chunkData.Chunk; var rootLodRequirements = chunk.GetNativeArray(RootLodRequirements); var instanceLodRequirements = chunk.GetNativeArray(InstanceLodRequirements); var chunkInstanceIndex = 0; var rootIndex = 0; float graceDistance = float.MaxValue; while (chunkInstanceIndex < chunkInstanceCount) { var rootLodRequirement = rootLodRequirements[rootIndex]; var rootInstanceCount = rootLodRequirement.InstanceCount; var rootLodDistance = math.select(DistanceScale * math.length(LODParams.cameraPos - rootLodRequirement.LOD.WorldReferencePosition), DistanceScale, isOrtho); float rootMinDist = math.select(rootLodRequirement.LOD.MinDist, 0.0f, forceLowLOD == 1); float rootMaxDist = rootLodRequirement.LOD.MaxDist; graceDistance = math.min(math.abs(rootLodDistance - rootMinDist), graceDistance); graceDistance = math.min(math.abs(rootLodDistance - rootMaxDist), graceDistance); var rootLodIntersect = (rootLodDistance < rootMaxDist) && (rootLodDistance >= rootMinDist); if (rootLodIntersect) { for (int i = 0; i < rootInstanceCount; i++) { var instanceLodRequirement = instanceLodRequirements[chunkInstanceIndex + i]; var instanceDistance = math.select(DistanceScale * math.length(LODParams.cameraPos - instanceLodRequirement.WorldReferencePosition), DistanceScale, isOrtho); var instanceLodIntersect = (instanceDistance < instanceLodRequirement.MaxDist) && (instanceDistance >= instanceLodRequirement.MinDist); graceDistance = math.min(math.abs(instanceDistance - instanceLodRequirement.MinDist), graceDistance); graceDistance = math.min(math.abs(instanceDistance - instanceLodRequirement.MaxDist), graceDistance); if (instanceLodIntersect) { var index = chunkInstanceIndex + i; var wordIndex = index >> 6; var bitIndex = index & 0x3f; var lodWord = chunkEntityLodEnabled.Enabled[wordIndex]; lodWord |= 1UL << bitIndex; chunkEntityLodEnabled.Enabled[wordIndex] = lodWord; } } } chunkInstanceIndex += rootInstanceCount; rootIndex++; } chunkData.MovementGraceFixed16 = Fixed16CamDistance.FromFloatFloor(graceDistance); chunkData.ForceLowLODPrevious = forceLowLOD; } } #if UNITY_EDITOR if (oldEntityLodEnabled.Enabled[0] != chunkEntityLodEnabled.Enabled[0] || oldEntityLodEnabled.Enabled[1] != chunkEntityLodEnabled.Enabled[1]) { Stats[ThreadIndex].Stats[CullingStats.kLodChanged]++; } #endif chunkData.InstanceLodEnableds = chunkEntityLodEnabled; }
#pragma warning restore 649 #endif public void Execute(ArchetypeChunk archetypeChunk, int chunkIndex, int firstEntityIndex) { var hybridChunkInfoArray = archetypeChunk.GetNativeArray(HybridChunkInfo); var chunkHeaderArray = archetypeChunk.GetNativeArray(ChunkHeader); for (var entityIndex = 0; entityIndex < archetypeChunk.Count; entityIndex++) { var hybridChunkInfo = hybridChunkInfoArray[entityIndex]; if (!hybridChunkInfo.Valid) { continue; } var chunkHeader = chunkHeaderArray[entityIndex]; #if UNITY_EDITOR Stats[ThreadIndex].Stats[CullingStats.kLodTotal]++; #endif var internalBatchIndex = hybridChunkInfo.InternalIndex; var chunkInstanceCount = chunkHeader.ArchetypeChunk.Count; var isOrtho = LODParams.isOrtho; ref var chunkCullingData = ref hybridChunkInfo.CullingData; ChunkInstanceLodEnabled chunkEntityLodEnabled = chunkCullingData.InstanceLodEnableds; #if UNITY_EDITOR ChunkInstanceLodEnabled oldEntityLodEnabled = chunkEntityLodEnabled; #endif var forceLowLOD = ForceLowLOD[internalBatchIndex]; if (0 == (chunkCullingData.Flags & HybridChunkCullingData.kFlagHasLodData)) { #if UNITY_EDITOR Stats[ThreadIndex].Stats[CullingStats.kLodNoRequirements]++; #endif chunkEntityLodEnabled.Enabled[0] = 0; chunkEntityLodEnabled.Enabled[1] = 0; chunkCullingData.ForceLowLODPrevious = forceLowLOD; for (int i = 0; i < chunkInstanceCount; ++i) { int wordIndex = i >> 6; int bitIndex = i & 63; chunkEntityLodEnabled.Enabled[wordIndex] |= 1ul << bitIndex; } } else { int diff = (int)chunkCullingData.MovementGraceFixed16 - CameraMoveDistanceFixed16; chunkCullingData.MovementGraceFixed16 = (ushort)math.max(0, diff); var graceExpired = chunkCullingData.MovementGraceFixed16 == 0; var forceLodChanged = forceLowLOD != chunkCullingData.ForceLowLODPrevious; if (graceExpired || forceLodChanged || DistanceScaleChanged) { chunkEntityLodEnabled.Enabled[0] = 0; chunkEntityLodEnabled.Enabled[1] = 0; #if UNITY_EDITOR Stats[ThreadIndex].Stats[CullingStats.kLodChunksTested]++; #endif var chunk = chunkHeader.ArchetypeChunk; var rootLodRequirements = chunk.GetNativeArray(RootLodRequirements); var instanceLodRequirements = chunk.GetNativeArray(InstanceLodRequirements); float graceDistance = float.MaxValue; for (int i = 0; i < chunkInstanceCount; i++) { var rootLodRequirement = rootLodRequirements[i]; var rootLodDistance = math.select( DistanceScale * math.length(LODParams.cameraPos - rootLodRequirement.LOD.WorldReferencePosition), DistanceScale, isOrtho); float rootMinDist = math.select(rootLodRequirement.LOD.MinDist, 0.0f, forceLowLOD == 1); float rootMaxDist = rootLodRequirement.LOD.MaxDist; graceDistance = math.min(math.abs(rootLodDistance - rootMinDist), graceDistance); graceDistance = math.min(math.abs(rootLodDistance - rootMaxDist), graceDistance); var rootLodIntersect = (rootLodDistance < rootMaxDist) && (rootLodDistance >= rootMinDist); if (rootLodIntersect) { var instanceLodRequirement = instanceLodRequirements[i]; var instanceDistance = math.select( DistanceScale * math.length(LODParams.cameraPos - instanceLodRequirement.WorldReferencePosition), DistanceScale, isOrtho); var instanceLodIntersect = (instanceDistance < instanceLodRequirement.MaxDist) && (instanceDistance >= instanceLodRequirement.MinDist); graceDistance = math.min(math.abs(instanceDistance - instanceLodRequirement.MinDist), graceDistance); graceDistance = math.min(math.abs(instanceDistance - instanceLodRequirement.MaxDist), graceDistance); if (instanceLodIntersect) { var index = i; var wordIndex = index >> 6; var bitIndex = index & 0x3f; var lodWord = chunkEntityLodEnabled.Enabled[wordIndex]; lodWord |= 1UL << bitIndex; chunkEntityLodEnabled.Enabled[wordIndex] = lodWord; } } } chunkCullingData.MovementGraceFixed16 = Fixed16CamDistance.FromFloatFloor(graceDistance); chunkCullingData.ForceLowLODPrevious = forceLowLOD; } } #if UNITY_EDITOR if (oldEntityLodEnabled.Enabled[0] != chunkEntityLodEnabled.Enabled[0] || oldEntityLodEnabled.Enabled[1] != chunkEntityLodEnabled.Enabled[1]) { Stats[ThreadIndex].Stats[CullingStats.kLodChanged]++; } #endif chunkCullingData.InstanceLodEnableds = chunkEntityLodEnabled; hybridChunkInfoArray[entityIndex] = hybridChunkInfo; }