private void InitializeBuffers() { int computeShaderInputSize = Marshal.SizeOf(typeof(ComputeShaderInputData)); int computeShaderOutputSize = Marshal.SizeOf(typeof(ComputeShaderOutputData)); m_argsBuffer = new ComputeBuffer(m_instances.Count * NUMBER_OF_ARGS_PER_INSTANCE, 5 * sizeof(uint), ComputeBufferType.IndirectArguments); m_positionsBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderInputSize, ComputeBufferType.Default); m_lodDistancesTempBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderInputSize, ComputeBufferType.Default); m_culledInstanceBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderOutputSize, ComputeBufferType.Default); m_isVisibleBuffer = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_scannedInstancePredicates = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_groupSumArray = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_scannedGroupSumBuffer = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_argsBuffer.SetData(m_args); m_positionsBuffer.SetData(instancesPositionsArray); m_lodDistancesTempBuffer.SetData(instancesPositionsArray); for (int i = 0; i < m_renderers.Count; i++) { IndirectRenderingMesh irm = m_renderers[i]; irm.Lod00MatPropBlock.SetBuffer("positionBuffer", m_culledInstanceBuffer); irm.Lod01MatPropBlock.SetBuffer("positionBuffer", m_culledInstanceBuffer); irm.Lod02MatPropBlock.SetBuffer("positionBuffer", m_culledInstanceBuffer); } }
private void DrawVisibleInstances() { if (enableSimpleShadows) { for (int i = 0; i < m_indirectMeshes.Length; i++) { int argsIndex = i * ARGS_BYTE_SIZE_PER_INSTANCE_TYPE; IndirectRenderingMesh irm = m_indirectMeshes[i]; Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, argsIndex + ARGS_BYTE_SIZE_PER_DRAW_CALL * 0, irm.lod00MatPropBlock, ShadowCastingMode.Off); Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, argsIndex + ARGS_BYTE_SIZE_PER_DRAW_CALL * 1, irm.lod01MatPropBlock, ShadowCastingMode.Off); Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, argsIndex + ARGS_BYTE_SIZE_PER_DRAW_CALL * 2, irm.lod02MatPropBlock, ShadowCastingMode.Off); Graphics.DrawMeshInstancedIndirect(irm.shadowMesh, 0, irm.material, m_bounds, m_argsBuffer, argsIndex + ARGS_BYTE_SIZE_PER_DRAW_CALL * 3, irm.shadowMatPropBlock, ShadowCastingMode.ShadowsOnly); } } else { for (int i = 0; i < m_indirectMeshes.Length; i++) { int argsIndex = i * ARGS_BYTE_SIZE_PER_INSTANCE_TYPE; IndirectRenderingMesh irm = m_indirectMeshes[i]; Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, argsIndex + ARGS_BYTE_SIZE_PER_DRAW_CALL * 0, irm.lod00MatPropBlock, ShadowCastingMode.On); Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, argsIndex + ARGS_BYTE_SIZE_PER_DRAW_CALL * 1, irm.lod01MatPropBlock, ShadowCastingMode.On); Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, argsIndex + ARGS_BYTE_SIZE_PER_DRAW_CALL * 2, irm.lod02MatPropBlock, ShadowCastingMode.On); } } if (debugDrawHiZ) { debugCamera.Render(); } }
private void LateUpdate() //OnPreCull() { if (m_renderers == null || m_renderers.Count == 0 || m_hiZBuffer.HiZDepthTexture == null || m_showHiZTexture == true) { return; } RunCompute(); // Draw visible objects if (m_debugStop == DebugStop.DontStop) { for (int i = 0; i < m_renderers.Count; i++) { IndirectRenderingMesh irm = m_renderers[i]; Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_drawBounds, m_argsBuffer, (i * 60) + 00, irm.Lod00MatPropBlock, m_shadowCastingMode, m_receiveShadows); Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_drawBounds, m_argsBuffer, (i * 60) + 20, irm.Lod01MatPropBlock, m_shadowCastingMode, m_receiveShadows); Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_drawBounds, m_argsBuffer, (i * 60) + 40, irm.Lod02MatPropBlock, m_shadowCastingMode, m_receiveShadows); } } }
private void DrawInstances() { ShadowCastingMode objShadowCastingMode = (m_enableLOD02Shadow) ? ShadowCastingMode.Off : ShadowCastingMode.On; for (int i = 0; i < m_renderers.Length; i++) { IndirectRenderingMesh irm = m_renderers[i]; if (!m_debugDisableMesh) { Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, (i * 80) + 00, irm.Lod00MatPropBlock, objShadowCastingMode, true); Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, (i * 80) + 20, irm.Lod01MatPropBlock, objShadowCastingMode, true); Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, (i * 80) + 40, irm.Lod02MatPropBlock, objShadowCastingMode, true); } if (m_enableLOD02Shadow) { Graphics.DrawMeshInstancedIndirect(irm.mesh, 0, irm.material, m_bounds, m_argsBuffer, (i * 80) + 60, irm.ShadowMatPropBlock, ShadowCastingMode.ShadowsOnly, false); } } }
public void Initialize() { m_00_lodSortingCSKernelID = m_00_lodSortingCS.FindKernel("BitonicSort"); m_00_lodSortingTransposeCSKernelID = m_00_lodSortingCS.FindKernel("MatrixTranspose"); m_01_occlusionKernelID = m_01_occlusionCS.FindKernel("CSMain"); m_02_scanInstancesKernelID = m_02_scanInstancesCS.FindKernel("CSMain"); m_03_scanGroupSumsKernelID = m_03_scanGroupSumsCS.FindKernel("CSMain"); m_04_copyInstanceDataKernelID = m_04_copyInstanceDataCS.FindKernel("CSMain"); m_05_calcInstanceOffsetsKernelID = m_05_calcInstanceOffsetsCS.FindKernel("CSMain"); int materialPropertyCounter = 0; int instanceCounter = 0; m_args = new uint[m_instances.Count * NUMBER_OF_ARGS_PER_INSTANCE]; for (int i = 0; i < m_instances.Count; i++) { IndirectRenderingMesh irm = new IndirectRenderingMesh(); IndirectInstanceData data = m_instances[i]; // Initialize Mesh irm.mesh = new Mesh(); irm.mesh.CombineMeshes( new CombineInstance[] { new CombineInstance() { mesh = data.lod00Mesh }, new CombineInstance() { mesh = data.lod01Mesh }, new CombineInstance() { mesh = data.lod02Mesh } }, true, // Merge Submeshes false, // Use Matrices false // Has lightmap data ); // Arguments int argsIndex = i * NUMBER_OF_ARGS_PER_INSTANCE; // Buffer with arguments has to have five integer numbers // LOD00 m_args[argsIndex + 0] = data.lod00Mesh.GetIndexCount(0); // 0 - index count per instance, m_args[argsIndex + 1] = 0; // 1 - instance count m_args[argsIndex + 2] = 0; // 2 - start index location m_args[argsIndex + 3] = 0; // 3 - base vertex location m_args[argsIndex + 4] = 0; // 4 - start instance location // LOD01 m_args[argsIndex + 5] = data.lod01Mesh.GetIndexCount(0); // 0 - index count per instance, m_args[argsIndex + 6] = 0; // 1 - instance count m_args[argsIndex + 7] = m_args[argsIndex + 0] + m_args[argsIndex + 2]; // 2 - start index location m_args[argsIndex + 8] = 0; // 3 - base vertex location m_args[argsIndex + 9] = 0; // 4 - start instance location // LOD02 m_args[argsIndex + 10] = data.lod02Mesh.GetIndexCount(0); // 0 - index count per instance, m_args[argsIndex + 11] = 0; // 1 - instance count m_args[argsIndex + 12] = m_args[argsIndex + 5] + m_args[argsIndex + 7]; // 2 - start index location m_args[argsIndex + 13] = 0; // 3 - base vertex location m_args[argsIndex + 14] = 0; // 4 - start instance location // Materials irm.Lod00MatPropBlock = new MaterialPropertyBlock(); irm.Lod01MatPropBlock = new MaterialPropertyBlock(); irm.Lod02MatPropBlock = new MaterialPropertyBlock(); // ---------------------------------------------------------- // Silly workaround for a shadow bug. // If we don't set a unique value to the property block we // only get shadows in one of our draw calls. irm.Lod00MatPropBlock.SetFloat("_Whatever" + materialPropertyCounter++, 1); irm.Lod01MatPropBlock.SetFloat("_Whatever" + materialPropertyCounter++, 2); irm.Lod02MatPropBlock.SetFloat("_Whatever" + materialPropertyCounter++, 3); // End of silly workaround! // ---------------------------------------------------------- irm.Lod00MatPropBlock.SetBuffer("positionBuffer", m_culledInstanceBuffer); irm.Lod01MatPropBlock.SetBuffer("positionBuffer", m_culledInstanceBuffer); irm.Lod02MatPropBlock.SetBuffer("positionBuffer", m_culledInstanceBuffer); irm.material = new Material(data.material); // Add the instance data (positions, rotations, scaling, bounds...) for (int j = 0; j < m_instances[i].positions.Length; j++) { instanceCounter++; IndirectInstanceData _data = m_instances[i]; ComputeShaderInputData newData = new ComputeShaderInputData(); Bounds b = new Bounds(); b.Encapsulate(_data.lod00Mesh.bounds); b.Encapsulate(_data.lod01Mesh.bounds); b.Encapsulate(_data.lod02Mesh.bounds); // b.extents *= _data.uniformScales[j]; newData.drawCallID = (uint)i * NUMBER_OF_ARGS_PER_INSTANCE; newData.position = _data.positions[j]; newData.rotation = _data.rotations[j]; newData.uniformScale = _data.uniformScales[j]; newData.boundsCenter = _data.positions[j]; newData.boundsExtents = b.extents * 0.5f; newData.distanceToCamera = Vector3.Distance(newData.position, m_camera.transform.position); irm.computeInstances.Add(newData); } // Add the data to the renderer list m_renderers.Add(irm); } // HACK! Padding the data so it becomes the power of two. if (!Mathf.IsPowerOfTwo(instanceCounter)) { int iterations = Mathf.NextPowerOfTwo(instanceCounter) - instanceCounter; for (int j = 0; j < iterations; j++) { m_renderers[0].computeInstances.Add(new ComputeShaderInputData() { drawCallID = HACK_POT_PADDING_DRAW_ID }); } } List <ComputeShaderInputData> tempInstancesPositionsList = new List <ComputeShaderInputData>(); for (int i = 0; i < m_renderers.Count; i++) { tempInstancesPositionsList.AddRange(m_renderers[i].computeInstances); } instancesPositionsArray = tempInstancesPositionsList.ToArray(); m_numberOfInstances = tempInstancesPositionsList.Count; InitializeBuffers(); }
private void LogStats() { if (!debugLogStats) { return; } debugLogStats = false; if (m_sb == null) { m_sb = new StringBuilder(); } uint[] argsData = new uint[m_instances.Length * NUMBER_OF_ARGS_PER_INSTANCE_TYPE]; m_argsBuffer.GetData(argsData); uint totalNumOfInstances = 0; uint totalNumOfIndices = 0; uint totalNumOfVertices = 0; uint totalShadowVertices = 0; uint totalShadowIndices = 0; m_sb.AppendLine("---------------"); int counter = 0; for (int i = 0; i < argsData.Length; i = i + 20) { IndirectRenderingMesh irm = m_indirectMeshes[counter]; if (i > 0) { m_sb.AppendLine(); } uint numOfLod00Instances = argsData[i + 1]; uint numOfLod01Instances = argsData[i + 6]; uint numOfLod02Instances = argsData[i + 11]; uint numOfLod00Indices = argsData[i + 0]; uint numOfLod01Indices = argsData[i + 5]; uint numOfLod02Indices = argsData[i + 10]; uint numOfLod00Vertices = (uint)irm.numOfVerticesLod00; uint numOfLod01Vertices = (uint)irm.numOfVerticesLod01; uint numOfLod02Vertices = (uint)irm.numOfVerticesLod02; uint numOfInstances = numOfLod00Instances + numOfLod01Instances + numOfLod02Instances; uint numOfIndices = numOfLod00Instances * numOfLod00Indices + numOfLod01Instances * numOfLod01Indices + numOfLod02Instances * numOfLod02Indices; uint numOfVertices = numOfLod00Instances * numOfLod00Vertices + numOfLod01Instances * numOfLod01Vertices + numOfLod02Instances * numOfLod02Vertices; uint numOfShadowIndices = (enableSimpleShadows) ? numOfInstances * numOfLod02Indices : numOfIndices; uint numOfShadowVertices = (enableSimpleShadows) ? numOfInstances * numOfLod02Vertices : numOfVertices; totalNumOfInstances += numOfInstances; totalNumOfIndices += numOfIndices; totalNumOfVertices += numOfVertices; totalShadowIndices += numOfShadowIndices; totalShadowVertices += numOfShadowVertices; m_sb.AppendLine("Instances: " + numOfInstances.ToString("N0") + " (" + numOfLod00Instances.ToString("N0") + ", " + numOfLod01Instances.ToString("N0") + ", " + numOfLod02Instances.ToString("N0") + ")" ); m_sb.AppendLine("Vertices: " + numOfVertices.ToString("N0") + " (" + numOfLod00Vertices.ToString("N0") + ", " + numOfLod01Vertices.ToString("N0") + ", " + numOfLod02Vertices.ToString("N0") + ")" ); m_sb.AppendLine("Indices: " + numOfIndices.ToString("N0") + " (" + numOfLod00Indices.ToString("N0") + ", " + numOfLod01Indices.ToString("N0") + ", " + numOfLod02Indices.ToString("N0") + ")" ); m_sb.AppendLine("Shadow: " + numOfShadowVertices.ToString("N0") + " Vertices " + numOfShadowIndices.ToString("N0") + " indices" ); counter++; } StringBuilder total = new StringBuilder(); total.Append("Total Instances: "); total.AppendLine(totalNumOfInstances.ToString("N0")); total.Append("Total Vertices: "); total.AppendLine(totalNumOfVertices.ToString("N0")); total.Append("Total Indices: "); total.AppendLine(totalNumOfIndices.ToString("N0")); total.Append("Shadow Vertices: "); total.AppendLine(totalShadowIndices.ToString("N0")); total.Append("Shadow Indices: "); total.AppendLine(totalShadowVertices.ToString("N0")); Debug.Log(total.ToString()); Debug.Log(m_sb.ToString()); }
public void Initialize(IndirectInstanceData[] _instances) { m_instances = _instances; m_numberOfInstanceTypes = m_instances.Length; m_lodSortingCSKernelID = lodSortingCS.FindKernel("BitonicSort"); m_lodSortingTransposeCSKernelID = lodSortingCS.FindKernel("MatrixTranspose"); m_occlusionKernelID = occlusionCS.FindKernel("CSMain"); m_scanInstancesKernelID = scanInstancesCS.FindKernel("CSMain"); m_scanGroupSumsKernelID = scanGroupSumsCS.FindKernel("CSMain"); m_copyInstanceDataKernelID = copyInstanceDataCS.FindKernel("CSMain"); int instanceCounter = 0; List <InstanceData> allInstancesPositionsList = new List <InstanceData>(); m_indirectMeshes = new IndirectRenderingMesh[m_numberOfInstanceTypes]; m_args = new uint[m_numberOfInstanceTypes * NUMBER_OF_ARGS_PER_INSTANCE_TYPE]; for (int i = 0; i < m_numberOfInstanceTypes; i++) { IndirectRenderingMesh irm = new IndirectRenderingMesh(); IndirectInstanceData data = m_instances[i]; // Initialize Mesh irm.numOfVerticesLod00 = (uint)data.lod00Mesh.vertexCount; irm.numOfVerticesLod01 = (uint)data.lod01Mesh.vertexCount; irm.numOfVerticesLod02 = (uint)data.lod02Mesh.vertexCount; irm.numOfVerticesShadow = (uint)data.shadowMesh.vertexCount; irm.numOfIndicesLod00 = data.lod00Mesh.GetIndexCount(0); irm.numOfIndicesLod01 = data.lod01Mesh.GetIndexCount(0); irm.numOfIndicesLod02 = data.lod02Mesh.GetIndexCount(0); irm.numOfIndicesShadow = data.shadowMesh.GetIndexCount(0); irm.mesh = new Mesh(); irm.mesh.CombineMeshes( new CombineInstance[] { new CombineInstance() { mesh = data.lod00Mesh }, new CombineInstance() { mesh = data.lod01Mesh }, new CombineInstance() { mesh = data.lod02Mesh } }, true, // Merge Submeshes false, // Use Matrices false // Has lightmap data ); irm.shadowMesh = data.shadowMesh; // Arguments int argsIndex = i * NUMBER_OF_ARGS_PER_INSTANCE_TYPE; // Buffer with arguments has to have five integer numbers // LOD00 m_args[argsIndex + 0] = irm.numOfIndicesLod00; // 0 - index count per instance, m_args[argsIndex + 1] = 0; // 1 - instance count m_args[argsIndex + 2] = 0; // 2 - start index location m_args[argsIndex + 3] = 0; // 3 - base vertex location m_args[argsIndex + 4] = 0; // 4 - start instance location // LOD01 m_args[argsIndex + 5] = irm.numOfIndicesLod01; // 0 - index count per instance, m_args[argsIndex + 6] = 0; // 1 - instance count m_args[argsIndex + 7] = m_args[argsIndex + 0] + m_args[argsIndex + 2]; // 2 - start index location m_args[argsIndex + 8] = 0; // 3 - base vertex location m_args[argsIndex + 9] = 0; // 4 - start instance location // LOD02 m_args[argsIndex + 10] = irm.numOfIndicesLod02; // 0 - index count per instance, m_args[argsIndex + 11] = 0; // 1 - instance count m_args[argsIndex + 12] = m_args[argsIndex + 5] + m_args[argsIndex + 7]; // 2 - start index location m_args[argsIndex + 13] = 0; // 3 - base vertex location m_args[argsIndex + 14] = 0; // 4 - start instance location // Shadow m_args[argsIndex + 15] = irm.numOfIndicesShadow; // 0 - index count per instance, m_args[argsIndex + 16] = 0; // 1 - instance count m_args[argsIndex + 17] = 0; // 2 - start index location m_args[argsIndex + 18] = 0; // 3 - base vertex location m_args[argsIndex + 19] = 0; // 4 - start instance location // Materials irm.material = new Material(data.material); // Add the instance data (positions, rotations, scaling, bounds...) for (int j = 0; j < m_instances[i].positions.Length; j++) { IndirectInstanceData _data = m_instances[i]; InstanceData newData = new InstanceData(); // Calculate the renderer bounds GameObject obj = Instantiate(m_instances[i].prefab); obj.transform.localScale = obj.transform.localScale; Renderer[] rends = obj.GetComponentsInChildren <Renderer>(); Bounds b = new Bounds(); for (int r = 0; r < rends.Length; r++) { b.Encapsulate(rends[r].bounds); } DestroyImmediate(obj); newData.drawDataID = (uint)(instanceCounter); newData.drawCallID = (uint)argsIndex; newData.position = _data.positions[j]; newData.rotation = _data.rotations[j]; newData.uniformScale = _data.uniformScales[j]; newData.boundsCenter = b.center;//_data.positions[j]; newData.boundsExtents = b.extents * _data.uniformScales[j]; newData.distanceToCamera = Vector3.Distance(_data.positions[j], mainCamera.transform.position); irm.computeInstances.Add(newData); allInstancesPositionsList.Add(newData); instanceCounter++; } // Add the data to the renderer list m_indirectMeshes[i] = irm; } InstanceData[] instancesPositionsArray = allInstancesPositionsList.ToArray(); m_numberOfInstances = allInstancesPositionsList.Count; int computeShaderInputSize = Marshal.SizeOf(typeof(InstanceData)); int computeShaderOutputSize = Marshal.SizeOf(typeof(InstanceDrawData)); m_argsBuffer = new ComputeBuffer(m_numberOfInstanceTypes * 20, sizeof(uint), ComputeBufferType.IndirectArguments); m_instanceDataBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderInputSize, ComputeBufferType.Default); m_instanceDrawDataBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderOutputSize, ComputeBufferType.Default); m_lodDistancesTempBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderInputSize, ComputeBufferType.Default); m_culledInstanceBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderOutputSize, ComputeBufferType.Default); m_isVisibleBuffer = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_scannedInstancePredicates = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_groupSumArray = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_scannedGroupSumBuffer = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_argsBuffer.SetData(m_args); m_instanceDataBuffer.SetData(instancesPositionsArray); m_lodDistancesTempBuffer.SetData(instancesPositionsArray); // Setup the Material Property blocks for our meshes... int materialPropertyCounter = 0; for (int i = 0; i < m_indirectMeshes.Length; i++) { IndirectRenderingMesh irm = m_indirectMeshes[i]; int argsIndex = i * NUMBER_OF_ARGS_PER_INSTANCE_TYPE; irm.lod00MatPropBlock = new MaterialPropertyBlock(); irm.lod01MatPropBlock = new MaterialPropertyBlock(); irm.lod02MatPropBlock = new MaterialPropertyBlock(); irm.shadowMatPropBlock = new MaterialPropertyBlock(); // ---------------------------------------------------------- // Silly workaround for a shadow bug in Unity. // If we don't set a unique value to the property block we // only get shadows in one of our draw calls. irm.lod00MatPropBlock.SetFloat("_Whatever", +materialPropertyCounter++); irm.lod01MatPropBlock.SetFloat("_Whatever", +materialPropertyCounter++); irm.lod02MatPropBlock.SetFloat("_Whatever", +materialPropertyCounter++); irm.shadowMatPropBlock.SetFloat("_Whatever", +materialPropertyCounter++); // End of silly workaround! // ---------------------------------------------------------- irm.lod00MatPropBlock.SetBuffer("_InstanceDrawDataBuffer", m_culledInstanceBuffer); irm.lod01MatPropBlock.SetBuffer("_InstanceDrawDataBuffer", m_culledInstanceBuffer); irm.lod02MatPropBlock.SetBuffer("_InstanceDrawDataBuffer", m_culledInstanceBuffer); irm.shadowMatPropBlock.SetBuffer("_InstanceDrawDataBuffer", m_culledInstanceBuffer); irm.lod00MatPropBlock.SetBuffer("_ArgsBuffer", m_argsBuffer); irm.lod01MatPropBlock.SetBuffer("_ArgsBuffer", m_argsBuffer); irm.lod02MatPropBlock.SetBuffer("_ArgsBuffer", m_argsBuffer); irm.shadowMatPropBlock.SetBuffer("_ArgsBuffer", m_argsBuffer); irm.lod00MatPropBlock.SetInt("_ArgsOffset", argsIndex + 4); irm.lod01MatPropBlock.SetInt("_ArgsOffset", argsIndex + 9); irm.lod02MatPropBlock.SetInt("_ArgsOffset", argsIndex + 14); irm.shadowMatPropBlock.SetInt("_ArgsOffset", argsIndex + 19); } // Create the buffer containing draw data for all instances m_createInstanceDrawBufferCSKernelID = createInstanceDrawBufferCS.FindKernel("CSMain"); createInstanceDrawBufferCS.SetBuffer(m_createInstanceDrawBufferCSKernelID, "_InstanceDataIn", m_instanceDataBuffer); createInstanceDrawBufferCS.SetBuffer(m_createInstanceDrawBufferCSKernelID, "_InstanceDataOut", m_instanceDrawDataBuffer); int groupX = m_numberOfInstances / (2 * SCAN_THREAD_GROUP_SIZE); createInstanceDrawBufferCS.Dispatch(m_createInstanceDrawBufferCSKernelID, groupX, 1, 1); CreateCommandBuffers(); }
public void Initialize(IndirectInstanceData[] _instances) { m_instances = _instances; m_numberOfInstanceTypes = m_instances.Length; m_00_lodSortingCSKernelID = m_00_lodSortingCS.FindKernel("BitonicSort"); m_00_lodSortingTransposeCSKernelID = m_00_lodSortingCS.FindKernel("MatrixTranspose"); m_01_occlusionKernelID = m_01_occlusionCS.FindKernel("CSMain"); m_02_scanInstancesKernelID = m_02_scanInstancesCS.FindKernel("CSMain"); m_03_scanGroupSumsKernelID = m_03_scanGroupSumsCS.FindKernel("CSMain"); m_04_copyInstanceDataKernelID = m_04_copyInstanceDataCS.FindKernel("CSMain"); m_05_calcInstanceOffsetsKernelID = m_05_calcInstanceOffsetsCS.FindKernel("CSMain"); int materialPropertyCounter = 0; int instanceCounter = 0; List <InstanceData> allInstancesPositionsList = new List <InstanceData>(); m_renderers = new IndirectRenderingMesh[m_numberOfInstanceTypes]; m_args = new uint[m_numberOfInstanceTypes * NUMBER_OF_ARGS_PER_INSTANCE]; for (int i = 0; i < m_numberOfInstanceTypes; i++) { IndirectRenderingMesh irm = new IndirectRenderingMesh(); IndirectInstanceData data = m_instances[i]; // Initialize Mesh irm.mesh = new Mesh(); irm.mesh.CombineMeshes( new CombineInstance[] { new CombineInstance() { mesh = data.lod00Mesh }, new CombineInstance() { mesh = data.lod01Mesh }, new CombineInstance() { mesh = data.lod02Mesh } }, true, // Merge Submeshes false, // Use Matrices false // Has lightmap data ); // Arguments int argsIndex = i * NUMBER_OF_ARGS_PER_INSTANCE; // Buffer with arguments has to have five integer numbers // LOD00 m_args[argsIndex + 0] = data.lod00Mesh.GetIndexCount(0); // 0 - index count per instance, m_args[argsIndex + 1] = 0; // 1 - instance count m_args[argsIndex + 2] = 0; // 2 - start index location m_args[argsIndex + 3] = 0; // 3 - base vertex location m_args[argsIndex + 4] = 0; // 4 - start instance location // LOD01 m_args[argsIndex + 5] = data.lod01Mesh.GetIndexCount(0); // 0 - index count per instance, m_args[argsIndex + 6] = 0; // 1 - instance count m_args[argsIndex + 7] = m_args[argsIndex + 0] + m_args[argsIndex + 2]; // 2 - start index location m_args[argsIndex + 8] = 0; // 3 - base vertex location m_args[argsIndex + 9] = 0; // 4 - start instance location // LOD02 m_args[argsIndex + 10] = data.lod02Mesh.GetIndexCount(0); // 0 - index count per instance, m_args[argsIndex + 11] = 0; // 1 - instance count m_args[argsIndex + 12] = m_args[argsIndex + 5] + m_args[argsIndex + 7]; // 2 - start index location m_args[argsIndex + 13] = 0; // 3 - base vertex location m_args[argsIndex + 14] = 0; // 4 - start instance location // Shadow m_args[argsIndex + 15] = m_args[argsIndex + 10]; // 0 - index count per instance, m_args[argsIndex + 16] = 0; // 1 - instance count m_args[argsIndex + 17] = m_args[argsIndex + 12]; // 2 - start index location m_args[argsIndex + 18] = 0; // 3 - base vertex location m_args[argsIndex + 19] = 0; // 4 - start instance location // Materials irm.Lod00MatPropBlock = new MaterialPropertyBlock(); irm.Lod01MatPropBlock = new MaterialPropertyBlock(); irm.Lod02MatPropBlock = new MaterialPropertyBlock(); irm.ShadowMatPropBlock = new MaterialPropertyBlock(); // ---------------------------------------------------------- // Silly workaround for a shadow bug. // If we don't set a unique value to the property block we // only get shadows in one of our draw calls. irm.Lod00MatPropBlock.SetFloat("_Whatever" + materialPropertyCounter++, 1); irm.Lod01MatPropBlock.SetFloat("_Whatever" + materialPropertyCounter++, 2); irm.Lod02MatPropBlock.SetFloat("_Whatever" + materialPropertyCounter++, 3); irm.ShadowMatPropBlock.SetFloat("_Whatever" + materialPropertyCounter++, 4); // End of silly workaround! // ---------------------------------------------------------- irm.material = new Material(data.material); // Add the instance data (positions, rotations, scaling, bounds...) for (int j = 0; j < m_instances[i].positions.Length; j++) { instanceCounter++; IndirectInstanceData _data = m_instances[i]; InstanceData newData = new InstanceData(); Bounds b = new Bounds(); b.Encapsulate(_data.lod00Mesh.bounds); b.Encapsulate(_data.lod01Mesh.bounds); b.Encapsulate(_data.lod02Mesh.bounds); b.extents *= _data.uniformScales[j]; newData.drawCallID = (uint)i * NUMBER_OF_ARGS_PER_INSTANCE; newData.position = _data.positions[j]; newData.rotation = _data.rotations[j]; newData.uniformScale = _data.uniformScales[j]; newData.boundsCenter = _data.positions[j]; newData.boundsExtents = b.extents; newData.distanceToCamera = Vector3.Distance(newData.position, m_camera.transform.position); irm.computeInstances.Add(newData); allInstancesPositionsList.Add(newData); } // Add the data to the renderer list m_renderers[i] = irm; } // HACK! // Padding the buffer with data so the size is in power of two. // Reason is that the current implementation of the Bitonic Sort // only supports that. On the todo list to fix! if (!Mathf.IsPowerOfTwo(instanceCounter)) { int iterations = Mathf.NextPowerOfTwo(instanceCounter) - instanceCounter; for (int j = 0; j < iterations; j++) { InstanceData newData = new InstanceData() { drawCallID = HACK_POT_PADDING_DRAW_ID }; m_renderers[0].computeInstances.Add(newData); allInstancesPositionsList.Add(newData); } } instancesPositionsArray = allInstancesPositionsList.ToArray(); m_numberOfInstances = allInstancesPositionsList.Count; int computeShaderInputSize = Marshal.SizeOf(typeof(InstanceData)); int computeShaderOutputSize = Marshal.SizeOf(typeof(InstanceDrawData)); m_argsBuffer = new ComputeBuffer(m_numberOfInstanceTypes, sizeof(uint) * NUMBER_OF_ARGS_PER_INSTANCE, ComputeBufferType.IndirectArguments); m_instanceDataBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderInputSize, ComputeBufferType.Default); m_lodDistancesTempBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderInputSize, ComputeBufferType.Default); m_culledInstanceBuffer = new ComputeBuffer(m_numberOfInstances, computeShaderOutputSize, ComputeBufferType.Default); m_isVisibleBuffer = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_scannedInstancePredicates = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_groupSumArray = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_scannedGroupSumBuffer = new ComputeBuffer(m_numberOfInstances, sizeof(uint), ComputeBufferType.Default); m_argsBuffer.SetData(m_args); m_instanceDataBuffer.SetData(instancesPositionsArray); m_lodDistancesTempBuffer.SetData(instancesPositionsArray); for (int i = 0; i < m_renderers.Length; i++) { IndirectRenderingMesh irm = m_renderers[i]; irm.Lod00MatPropBlock.SetBuffer("_InstanceDrawDataBuffer", m_culledInstanceBuffer); irm.Lod01MatPropBlock.SetBuffer("_InstanceDrawDataBuffer", m_culledInstanceBuffer); irm.Lod02MatPropBlock.SetBuffer("_InstanceDrawDataBuffer", m_culledInstanceBuffer); irm.ShadowMatPropBlock.SetBuffer("_InstanceDrawDataBuffer", m_culledInstanceBuffer); int argsIndex = i * NUMBER_OF_ARGS_PER_INSTANCE; if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer) { irm.Lod00MatPropBlock.SetBuffer("_ArgsBuffer", m_argsBuffer); irm.Lod01MatPropBlock.SetBuffer("_ArgsBuffer", m_argsBuffer); irm.Lod02MatPropBlock.SetBuffer("_ArgsBuffer", m_argsBuffer); irm.ShadowMatPropBlock.SetBuffer("_ArgsBuffer", m_argsBuffer); irm.Lod00MatPropBlock.SetInt("_ArgsOffset", argsIndex + 4); irm.Lod01MatPropBlock.SetInt("_ArgsBuffer", argsIndex + 9); irm.Lod02MatPropBlock.SetInt("_ArgsBuffer", argsIndex + 14); irm.ShadowMatPropBlock.SetInt("_ArgsBuffer", argsIndex + 19); } } }