protected override void OnUpdate() { for (int i = 0; i < POSITION_SLICES; i++) { ClearQueueJob clearQueueJob = new ClearQueueJob { nativeQueue = nativeQueueArray[i] }; jobHandleArray[i] = clearQueueJob.Schedule(); } JobHandle.CompleteAll(jobHandleArray); Camera camera = Camera.main; float cameraWidth = camera.aspect * camera.orthographicSize; float3 cameraPosition = camera.transform.position; float marginX = cameraWidth / 10f; float xMin = cameraPosition.x - cameraWidth - marginX; float xMax = cameraPosition.x + cameraWidth + marginX; float cameraSliceSize = camera.orthographicSize * 2f / POSITION_SLICES; float yBottom = cameraPosition.y - camera.orthographicSize; // Bottom cull position float yTop_1 = cameraPosition.y + camera.orthographicSize; // Top most cull position float yTop_2 = yTop_1 - cameraSliceSize * 1f; float yTop_3 = yTop_1 - cameraSliceSize * 2f; float yTop_4 = yTop_1 - cameraSliceSize * 3f; float yTop_5 = yTop_1 - cameraSliceSize * 4f; float yTop_6 = yTop_1 - cameraSliceSize * 5f; float yTop_7 = yTop_1 - cameraSliceSize * 6f; float yTop_8 = yTop_1 - cameraSliceSize * 7f; float yTop_9 = yTop_1 - cameraSliceSize * 8f; float yTop_10 = yTop_1 - cameraSliceSize * 9f; float yTop_11 = yTop_1 - cameraSliceSize * 10f; float yTop_12 = yTop_1 - cameraSliceSize * 11f; float yTop_13 = yTop_1 - cameraSliceSize * 12f; float yTop_14 = yTop_1 - cameraSliceSize * 13f; float yTop_15 = yTop_1 - cameraSliceSize * 14f; float yTop_16 = yTop_1 - cameraSliceSize * 15f; float yTop_17 = yTop_1 - cameraSliceSize * 16f; float yTop_18 = yTop_1 - cameraSliceSize * 17f; float yTop_19 = yTop_1 - cameraSliceSize * 18f; float yTop_20 = yTop_1 - cameraSliceSize * 19f; float marginY = camera.orthographicSize / 10f; yTop_1 += marginY; yBottom -= marginY; CullAndSortNativeQueueJob cullAndSortNativeQueueJob = new CullAndSortNativeQueueJob { xMin = xMin, xMax = xMax, yBottom = yBottom, yTop_1 = yTop_1, yTop_2 = yTop_2, yTop_3 = yTop_3, yTop_4 = yTop_4, yTop_5 = yTop_5, yTop_6 = yTop_6, yTop_7 = yTop_7, yTop_8 = yTop_8, yTop_9 = yTop_9, yTop_10 = yTop_10, yTop_11 = yTop_11, yTop_12 = yTop_12, yTop_13 = yTop_13, yTop_14 = yTop_14, yTop_15 = yTop_15, yTop_16 = yTop_16, yTop_17 = yTop_17, yTop_18 = yTop_18, yTop_19 = yTop_19, yTop_20 = yTop_20, nativeQueue_1 = nativeQueueArray[0].AsParallelWriter(), nativeQueue_2 = nativeQueueArray[1].AsParallelWriter(), nativeQueue_3 = nativeQueueArray[2].AsParallelWriter(), nativeQueue_4 = nativeQueueArray[3].AsParallelWriter(), nativeQueue_5 = nativeQueueArray[4].AsParallelWriter(), nativeQueue_6 = nativeQueueArray[5].AsParallelWriter(), nativeQueue_7 = nativeQueueArray[6].AsParallelWriter(), nativeQueue_8 = nativeQueueArray[7].AsParallelWriter(), nativeQueue_9 = nativeQueueArray[8].AsParallelWriter(), nativeQueue_10 = nativeQueueArray[9].AsParallelWriter(), nativeQueue_11 = nativeQueueArray[10].AsParallelWriter(), nativeQueue_12 = nativeQueueArray[11].AsParallelWriter(), nativeQueue_13 = nativeQueueArray[12].AsParallelWriter(), nativeQueue_14 = nativeQueueArray[13].AsParallelWriter(), nativeQueue_15 = nativeQueueArray[14].AsParallelWriter(), nativeQueue_16 = nativeQueueArray[15].AsParallelWriter(), nativeQueue_17 = nativeQueueArray[16].AsParallelWriter(), nativeQueue_18 = nativeQueueArray[17].AsParallelWriter(), nativeQueue_19 = nativeQueueArray[18].AsParallelWriter(), nativeQueue_20 = nativeQueueArray[19].AsParallelWriter() }; JobHandle cullAndSortNativeQueueJobHandle = cullAndSortNativeQueueJob.Schedule(this); cullAndSortNativeQueueJobHandle.Complete(); int visibleEntityTotal = 0; for (int i = 0; i < POSITION_SLICES; i++) { visibleEntityTotal += nativeQueueArray[i].Count; } for (int i = 0; i < POSITION_SLICES; i++) { NativeArray <RenderData> nativeArray = new NativeArray <RenderData>(nativeQueueArray[i].Count, Allocator.TempJob); nativeArrayArray[i] = nativeArray; } for (int i = 0; i < POSITION_SLICES; i++) { NativeQueueToArrayJob nativeQueueToArrayJob = new NativeQueueToArrayJob { nativeQueue = nativeQueueArray[i], nativeArray = nativeArrayArray[i], }; jobHandleArray[i] = nativeQueueToArrayJob.Schedule(); } JobHandle.CompleteAll(jobHandleArray); // Sort by position for (int i = 0; i < POSITION_SLICES; i++) { SortByPositionJob sortByPositionJob = new SortByPositionJob { sortArray = nativeArrayArray[i], comparer = positionComparer }; jobHandleArray[i] = sortByPositionJob.Schedule(); } JobHandle.CompleteAll(jobHandleArray); // Fill up individual Arrays NativeArray <Matrix4x4> matrixArray = new NativeArray <Matrix4x4>(visibleEntityTotal, Allocator.TempJob); NativeArray <Vector4> uvArray = new NativeArray <Vector4>(visibleEntityTotal, Allocator.TempJob); int startingIndex = 0; for (int i = 0; i < POSITION_SLICES; i++) { //if (i != 4) continue; FillArraysParallelJob fillArraysParallelJob = new FillArraysParallelJob { nativeArray = nativeArrayArray[i], matrixArray = matrixArray, uvArray = uvArray, startingIndex = startingIndex }; startingIndex += nativeArrayArray[i].Length; jobHandleArray[i] = fillArraysParallelJob.Schedule(nativeArrayArray[i].Length, 10); } JobHandle.CompleteAll(jobHandleArray); //jobHandleArray.Dispose(); for (int i = 0; i < POSITION_SLICES; i++) { nativeArrayArray[i].Dispose(); } // Slice Arrays and Draw InitDrawMeshInstancedSlicedData(); for (int i = 0; i < visibleEntityTotal; i += DRAW_MESH_INSTANCED_SLICE_COUNT) { int sliceSize = math.min(visibleEntityTotal - i, DRAW_MESH_INSTANCED_SLICE_COUNT); NativeArray <Matrix4x4> .Copy(matrixArray, i, matrixInstancedArray, 0, sliceSize); NativeArray <Vector4> .Copy(uvArray, i, uvInstancedArray, 0, sliceSize); materialPropertyBlock.SetVectorArray(shaderMainTexUVid, uvInstancedArray); Graphics.DrawMeshInstanced(mesh, 0, material, matrixInstancedArray, sliceSize, materialPropertyBlock); } matrixArray.Dispose(); uvArray.Dispose(); }
// // // //END OF SPLIT MULTITHREADED CODE /// // // // // // //TODO Basically re-do this code once per different sprite tag, e.g once for User and once for Goblins, then we do 1 draw call per spritesheet protected override void OnUpdate() { //Get our entity reference EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager; EntityQuery entityQuery = GetEntityQuery( typeof(SpriteSheetData)); //TODO Replace spritesheetdata with our tag? or seperate after we have them all by our identifer tags NativeArray <Entity> entitiesToDraw = entityQuery.ToEntityArray(Allocator.TempJob); Entity e = entitiesToDraw[ 0]; //Assume all entities share the shared data here (spritesheet cells, cell size, materials, etc. //Grab other shared data, DynamicBuffer <AnimationClip> animationClips = entityManager.GetBuffer <AnimationClip>(e); MaterialPropertyBlock shaderVariables = new MaterialPropertyBlock(); // //Per different Sprite // SpriteSheetData _spriteSheetData = entityManager.GetComponentData <SpriteSheetData>(e); //Get one per different sprite Vector2 _spriteSheetUVs = _spriteSheetData.GridUVs; MeshData _meshData = entityManager.GetSharedComponentData <MeshData>(e); // // End per different sprite (e.g we can re-use these values for each entity with a tag (.eg goblin) // EntityQuery query = GetEntityQuery(typeof(UniqueAnimationData), typeof(Translation)); NativeArray <UniqueAnimationData> uniqueAnimationDatas = query.ToComponentDataArray <UniqueAnimationData>(Allocator.TempJob); NativeQueue <RenderData> renderQueue1 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> renderQueue2 = new NativeQueue <RenderData>(Allocator.TempJob); Camera camera = Camera.main; float3 cameraPos = camera.transform.position; float yBottom = cameraPos.y - camera.orthographicSize; float yTop1 = cameraPos.y + camera.orthographicSize; float yTop2 = cameraPos.y + 0f; CullAndSortJob cullAndSortJob = new CullAndSortJob() { YBottom = yBottom, YTop1 = yTop1, YTop2 = yTop2, nativeQueue_1 = renderQueue1.AsParallelWriter(), nativeQueue_2 = renderQueue2.AsParallelWriter(), spriteSheetUVs = _spriteSheetData.GridUVs }; JobHandle jobHandle = cullAndSortJob.Schedule(this); jobHandle.Complete(); NativeArray <JobHandle> jobHandles = new NativeArray <JobHandle>(2, Allocator.TempJob); NativeArray <RenderData> renderArray1 = new NativeArray <RenderData>(renderQueue1.Count, Allocator.TempJob); NativeArray <RenderData> renderArray2 = new NativeArray <RenderData>(renderQueue2.Count, Allocator.TempJob); RenderQueueToArrayJob renderQueueToArrayJob1 = new RenderQueueToArrayJob() { renderQueue1 = renderQueue1, renderArray = renderArray1 }; RenderQueueToArrayJob renderQueueToArrayJob2 = new RenderQueueToArrayJob() { renderQueue1 = renderQueue2, renderArray = renderArray2 }; jobHandles[0] = renderQueueToArrayJob1.Schedule(); jobHandles[1] = renderQueueToArrayJob2.Schedule(); JobHandle.CompleteAll(jobHandles); renderQueue1.Dispose(); renderQueue2.Dispose(); SortByPositionJob sortByPositionJob1 = new SortByPositionJob() { sortArray = renderArray1 }; SortByPositionJob sortByPositionJob2 = new SortByPositionJob() { sortArray = renderArray2 }; jobHandles[0] = sortByPositionJob1.Schedule(); jobHandles[1] = sortByPositionJob2.Schedule(); JobHandle.CompleteAll(jobHandles); int visibleEntityTotal = renderArray1.Length + renderArray2.Length; NativeArray <Matrix4x4> matrixArray = new NativeArray <Matrix4x4>(visibleEntityTotal, Allocator.TempJob); NativeArray <Vector4> uvArray = new NativeArray <Vector4>(visibleEntityTotal, Allocator.TempJob); FillArraysParralelJob fillArraysParralelJob1 = new FillArraysParralelJob() { nativeArray = renderArray1, matrixArray = matrixArray, uvArray = uvArray, startingIndex = 0 }; jobHandles[0] = fillArraysParralelJob1.Schedule(renderArray1.Length, 10); FillArraysParralelJob fillArraysParralelJob2 = new FillArraysParralelJob() { nativeArray = renderArray2, matrixArray = matrixArray, uvArray = uvArray, startingIndex = renderArray1.Length }; jobHandles[1] = fillArraysParralelJob2.Schedule(renderArray2.Length, 10); JobHandle.CompleteAll(jobHandles); int shaderPropertyId = Shader.PropertyToID("_MainTex_UV"); Mesh mesh = MaterialStore.GetInstance().GetMeshById(_meshData.GetMeshID()); int sliceCount = 1023; Matrix4x4[] matrixInstancedArray = new Matrix4x4[sliceCount]; Vector4[] uvInstancedArray = new Vector4[sliceCount]; for (int i = 0; i < uniqueAnimationDatas.Length; i += sliceCount) { int sliceSize = math.min(uniqueAnimationDatas.Length - i, sliceCount); NativeArray <Matrix4x4> .Copy(matrixArray, i, matrixInstancedArray, 0, sliceSize); NativeArray <Vector4> .Copy(uvArray, i, uvInstancedArray, 0, sliceSize); shaderVariables.SetVectorArray(shaderPropertyId, uvInstancedArray); Graphics.DrawMeshInstanced( mesh, 0, _meshData.GetMaterial(), matrixInstancedArray, sliceSize, shaderVariables ); } matrixArray.Dispose(); uvArray.Dispose(); uniqueAnimationDatas.Dispose(); entitiesToDraw.Dispose(); jobHandles.Dispose(); renderArray1.Dispose(); renderArray2.Dispose(); }
protected override void OnUpdate() { EntityQuery entityQuery = GetEntityQuery(typeof(Translation), typeof(SpriteSheetComponentData)); NativeArray <SpriteSheetComponentData> animationDataQuery = entityQuery.ToComponentDataArray <SpriteSheetComponentData>(Allocator.TempJob); NativeArray <Translation> translationArray = entityQuery.ToComponentDataArray <Translation>(Allocator.TempJob); NativeQueue <RenderData> nativeQueue_1 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> nativeQueue_2 = new NativeQueue <RenderData>(Allocator.TempJob); Camera cameraMain = Camera.main; float3 cameraPosition = cameraMain.transform.position; float yBottom = cameraPosition.y - cameraMain.orthographicSize; float yTop_1 = cameraPosition.y + cameraMain.orthographicSize; float yTop_2 = cameraPosition.y + 0f; CullAndSortJob cullAndSortJob = new CullAndSortJob { yBottom = yBottom, yTop_1 = yTop_1, yTop_2 = yTop_2, nativeQueue1 = nativeQueue_1.AsParallelWriter(), nativeQueue2 = nativeQueue_2.AsParallelWriter() }; JobHandle jobHandle = cullAndSortJob.Schedule(this); jobHandle.Complete(); animationDataQuery.Dispose(); translationArray.Dispose(); NativeArray <RenderData> nativeArray_1 = nativeQueue_1.ToArray(Allocator.TempJob); NativeArray <RenderData> nativeArray_2 = nativeQueue_2.ToArray(Allocator.TempJob); nativeQueue_1.Dispose(); nativeQueue_2.Dispose(); NativeArray <JobHandle> jobHandleArray = new NativeArray <JobHandle>(2, Allocator.TempJob); SortByPositionJob sortByPositionJob_1 = new SortByPositionJob { dataArray = nativeArray_1 }; jobHandleArray[0] = sortByPositionJob_1.Schedule(); SortByPositionJob sortByPositionJob_2 = new SortByPositionJob { dataArray = nativeArray_2 }; jobHandleArray[1] = sortByPositionJob_2.Schedule(); JobHandle.CompleteAll(jobHandleArray); int visibleEntityTotal = nativeArray_1.Length + nativeArray_2.Length; NativeArray <Matrix4x4> matrixArray = new NativeArray <Matrix4x4>(visibleEntityTotal, Allocator.TempJob); NativeArray <Vector4> uvArray = new NativeArray <Vector4>(visibleEntityTotal, Allocator.TempJob); FillArraysParrallelJob fillArraysParrallelJob_1 = new FillArraysParrallelJob { nativeArray = nativeArray_1, matrixArray = matrixArray, uvArray = uvArray, startingIndex = 0 }; jobHandleArray[0] = fillArraysParrallelJob_1.Schedule(nativeArray_1.Length, 10); FillArraysParrallelJob fillArraysParrallelJob_2 = new FillArraysParrallelJob { nativeArray = nativeArray_2, matrixArray = matrixArray, uvArray = uvArray, startingIndex = nativeArray_1.Length }; jobHandleArray[1] = fillArraysParrallelJob_2.Schedule(nativeArray_2.Length, 10); JobHandle.CompleteAll(jobHandleArray); nativeArray_1.Dispose(); nativeArray_2.Dispose(); MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); Vector4[] uv = new Vector4[1]; Mesh quadMesh = GameEntity.GetInstance().quadMesh; Material material = GameEntity.GetInstance().walkingSpriteSheetMaterial; int shaderPropertyId = Shader.PropertyToID("_MainTex_UV"); int sliceCount = 1023; Matrix4x4[] matrixInstancedArray = new Matrix4x4[sliceCount]; Vector4[] uvInstancedArray = new Vector4[sliceCount]; for (int i = 0; i < matrixArray.Length; i += sliceCount) { int sliceSize = Mathf.Min(sliceCount, matrixArray.Length - i); NativeArray <Matrix4x4> .Copy(matrixArray, i, matrixInstancedArray, 0, sliceSize); NativeArray <Vector4> .Copy(uvArray, i, uvInstancedArray, 0, sliceSize); materialPropertyBlock.SetVectorArray(shaderPropertyId, uvInstancedArray); Graphics.DrawMeshInstanced( quadMesh, 0, material, matrixInstancedArray, sliceSize, materialPropertyBlock ); } matrixArray.Dispose(); uvArray.Dispose(); jobHandleArray.Dispose(); }
protected override void OnUpdate() { NativeQueue <RenderData> nativeQueue_1 = new NativeQueue <RenderData>(Allocator.TempJob); NativeQueue <RenderData> nativeQueue_2 = new NativeQueue <RenderData>(Allocator.TempJob); Camera camera = Camera.main; float3 cameraPosition = camera.transform.position; float yBottom = cameraPosition.y - camera.orthographicSize; float yTop_1 = cameraPosition.y + camera.orthographicSize; float yTop_2 = cameraPosition.y + 0f; CullAndSortJob cullAndSortJob = new CullAndSortJob { yBottom = yBottom, yTop_1 = yTop_1, yTop_2 = yTop_2, nativeQueue_1 = nativeQueue_1.ToConcurrent(), nativeQueue_2 = nativeQueue_2.ToConcurrent(), }; JobHandle jobHandle = cullAndSortJob.Schedule(this); jobHandle.Complete(); // Convert Queues into Arrays for Sorting NativeArray <RenderData> nativeArray_1 = new NativeArray <RenderData>(nativeQueue_1.Count, Allocator.TempJob); NativeArray <RenderData> nativeArray_2 = new NativeArray <RenderData>(nativeQueue_2.Count, Allocator.TempJob); NativeArray <JobHandle> jobHandleArray = new NativeArray <JobHandle>(2, Allocator.TempJob); NativeQueueToArrayJob nativeQueueToArrayJob_1 = new NativeQueueToArrayJob { nativeQueue = nativeQueue_1, nativeArray = nativeArray_1, }; jobHandleArray[0] = nativeQueueToArrayJob_1.Schedule(); NativeQueueToArrayJob nativeQueueToArrayJob_2 = new NativeQueueToArrayJob { nativeQueue = nativeQueue_2, nativeArray = nativeArray_2, }; jobHandleArray[1] = nativeQueueToArrayJob_2.Schedule(); JobHandle.CompleteAll(jobHandleArray); nativeQueue_1.Dispose(); nativeQueue_2.Dispose(); // Sort arrays by position SortByPositionJob sortByPositionJob_1 = new SortByPositionJob { sortArray = nativeArray_1, }; jobHandleArray[0] = sortByPositionJob_1.Schedule(); SortByPositionJob sortByPositionJob_2 = new SortByPositionJob { sortArray = nativeArray_2, }; jobHandleArray[1] = sortByPositionJob_2.Schedule(); JobHandle.CompleteAll(jobHandleArray); int visibleEntityTotal = nativeArray_1.Length + nativeArray_2.Length; // Grab sliced arrays and merge them all into one NativeArray <Matrix4x4> matrixArray = new NativeArray <Matrix4x4>(visibleEntityTotal, Allocator.TempJob); NativeArray <Vector4> uvArray = new NativeArray <Vector4>(visibleEntityTotal, Allocator.TempJob); FillArraysParallelJob fillArraysParallelJob_1 = new FillArraysParallelJob { nativeArray = nativeArray_1, matrixArray = matrixArray, uvArray = uvArray, startingIndex = 0, }; jobHandleArray[0] = fillArraysParallelJob_1.Schedule(nativeArray_1.Length, 10); FillArraysParallelJob fillArraysParallelJob_2 = new FillArraysParallelJob { nativeArray = nativeArray_2, matrixArray = matrixArray, uvArray = uvArray, startingIndex = nativeArray_1.Length, }; jobHandleArray[1] = fillArraysParallelJob_2.Schedule(nativeArray_2.Length, 10); JobHandle.CompleteAll(jobHandleArray); jobHandleArray.Dispose(); nativeArray_1.Dispose(); nativeArray_2.Dispose(); // Draw MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); Vector4[] uv = new Vector4[1]; Mesh quadMesh = GameController.Instance.Mesh; Material material = GameController.Instance.Material; int shaderPropertyId = Shader.PropertyToID("_MainTex_UV"); int sliceCount = 1023; Matrix4x4[] matrixInstancedArray = new Matrix4x4[sliceCount]; Vector4[] uvInstancedArray = new Vector4[sliceCount]; for (int i = 0; i < visibleEntityTotal; i += sliceCount) { int sliceSize = math.min(visibleEntityTotal - i, sliceCount); NativeArray <Matrix4x4> .Copy(matrixArray, i, matrixInstancedArray, 0, sliceSize); NativeArray <Vector4> .Copy(uvArray, i, uvInstancedArray, 0, sliceSize); materialPropertyBlock.SetVectorArray(shaderPropertyId, uvInstancedArray); Graphics.DrawMeshInstanced( quadMesh, 0, material, matrixInstancedArray, sliceSize, materialPropertyBlock ); } matrixArray.Dispose(); uvArray.Dispose(); }