Exemplo n.º 1
0
        public ComputeBuffer Result(int chunkCoordX, int chunkCoordY, int chunkCoordZ, int cubesPerAxis, ref FragRegionIndex fragRegionIndex)
        {
            //Total number of cubes inside a chunk
            int cubesPerChunk   = cubesPerAxis * cubesPerAxis * cubesPerAxis;
            int indexesPerChunk = cubesPerAxis * cubesPerAxis;

            //How many to process on a single thread
            int processPerThread = Mathf.CeilToInt(cubesPerAxis / 8.0f);

            //RWStructuredBuffer sets
            ComputeBuffer voxelsBuffer           = new ComputeBuffer(cubesPerChunk, GPUVoxel.Stride);
            ComputeBuffer fragRegionIndexsBuffer = new ComputeBuffer(indexesPerChunk, Stride.IntStride);

            NoiseShader.SetBuffer(Kernel, "Voxels", voxelsBuffer);
            NoiseShader.SetBuffer(Kernel, "RegionIndexes", fragRegionIndexsBuffer);

            //Sets
            NoiseShader.SetInts("ChunkCoord", new int[3] {
                chunkCoordX, chunkCoordY, chunkCoordZ
            });

            //Run kernal
            NoiseShader.Dispatch(Kernel, processPerThread, processPerThread, processPerThread);

            //Output
            int[] fragRegionIndexOutput = new int[indexesPerChunk];
            fragRegionIndexsBuffer.GetData(fragRegionIndexOutput);

            //Process indexes for fragment shader
            for (int i = 0; i < fragRegionIndexOutput.Length; i++)
            {
                if (fragRegionIndex.Index0 == fragRegionIndexOutput[i])
                {
                    continue;
                }
                if (fragRegionIndex.Index0 == -1)
                {
                    fragRegionIndex.Index0 = fragRegionIndexOutput[i];
                    continue;
                }

                if (fragRegionIndex.Index1 == fragRegionIndexOutput[i])
                {
                    continue;
                }
                if (fragRegionIndex.Index1 == -1)
                {
                    fragRegionIndex.Index1 = fragRegionIndexOutput[i];
                    continue;
                }

                if (fragRegionIndex.Index2 == fragRegionIndexOutput[i])
                {
                    continue;
                }
                if (fragRegionIndex.Index2 == -1)
                {
                    fragRegionIndex.Index2 = fragRegionIndexOutput[i];
                    continue;
                }

                if (fragRegionIndex.Index3 == fragRegionIndexOutput[i])
                {
                    continue;
                }
                if (fragRegionIndex.Index3 == -1)
                {
                    fragRegionIndex.Index3 = fragRegionIndexOutput[i];
                    break;
                }
            }

            //Get rid of buffer data
            fragRegionIndexsBuffer.Dispose();

            return(voxelsBuffer);
        }
        public (Vector3[], int[], FragRegionIndex) Result(int chunkCoordX, int chunkCoordY, int chunkCoordZ, int cubesPerAxis, VoxelNoiseGenerator noiseGenerator)
        {
            int chunkOffsetX         = chunkCoordX * 3;
            int chunkOffsetY         = chunkCoordY * 3;
            int chunkOffsetZ         = chunkCoordZ * 3;
            int maxRectangleGPUCount = (cubesPerAxis * cubesPerAxis * cubesPerAxis) * 5;

            //How many to process on a single thread
            int processPerThread = Mathf.CeilToInt(cubesPerAxis / 8.0f);

            //RWStructuredBuffer sets
            ComputeBuffer rectanglesBuffer = new ComputeBuffer(maxRectangleGPUCount, GPURectangle.Stride, ComputeBufferType.Append);
            ComputeBuffer rectCountBuffer  = new ComputeBuffer(1, Stride.IntStride, ComputeBufferType.Raw);

            rectanglesBuffer.SetCounterValue(0);

            FragRegionIndex fragRegionIndex = new FragRegionIndex
            {
                Index0 = -1,
                Index1 = -1,
                Index2 = -1,
                Index3 = -1,
            };

            //Generate sub chunks to combine into a whole chunk
            for (int x = 0; x < 3; x++)
            {
                for (int y = 0; y < 3; y++)
                {
                    for (int z = 0; z < 3; z++)
                    {
                        //Run noise kernal
                        ComputeBuffer noiseShader = noiseGenerator.Result(chunkOffsetX + x, chunkOffsetY + y, chunkOffsetZ + z, cubesPerAxis, ref fragRegionIndex);

                        //Run face kernal
                        FaceLeftGenerator.Result(new Vector3Int(x, y, z), new Vector3Int(processPerThread, 1, 1), noiseShader, rectanglesBuffer);
                        FaceForwardGenerator.Result(new Vector3Int(x, y, z), new Vector3Int(1, 1, processPerThread), noiseShader, rectanglesBuffer);
                        FaceRightGenerator.Result(new Vector3Int(x, y, z), new Vector3Int(processPerThread, 1, 1), noiseShader, rectanglesBuffer);
                        FaceBackwardGenerator.Result(new Vector3Int(x, y, z), new Vector3Int(1, 1, processPerThread), noiseShader, rectanglesBuffer);
                        FaceUpGenerator.Result(new Vector3Int(x, y, z), new Vector3Int(1, processPerThread, 1), noiseShader, rectanglesBuffer);
                        FaceDownGenerator.Result(new Vector3Int(x, y, z), new Vector3Int(1, processPerThread, 1), noiseShader, rectanglesBuffer);

                        //Get rid of buffer data
                        noiseShader.Dispose();
                    }
                }
            }

            //Grab output count
            ComputeBuffer.CopyCount(rectanglesBuffer, rectCountBuffer, 0);
            int[] rectCount = { 0 };
            rectCountBuffer.GetData(rectCount);

            //Outputs
            GPURectangle[] rectangleGPUOutput = new GPURectangle[rectCount[0]];
            Vector3[]      verticesOutput     = new Vector3[rectangleGPUOutput.Length * 4];
            int[]          trianglesOutput    = new int[rectangleGPUOutput.Length * 6];

            //Grab outputs
            rectanglesBuffer.GetData(rectangleGPUOutput, 0, 0, rectCount[0]);

            //Get rid of buffer data
            rectanglesBuffer.Dispose();
            rectCountBuffer.Dispose();

            //Process triangles
            for (int i = 0; i < rectangleGPUOutput.Length; i++)
            {
                int vertIndex = i * 4;
                int triIndex  = i * 6;

                //Vertices
                verticesOutput[vertIndex]     = rectangleGPUOutput[i].VertexA;
                verticesOutput[vertIndex + 1] = rectangleGPUOutput[i].VertexB;
                verticesOutput[vertIndex + 2] = rectangleGPUOutput[i].VertexC;
                verticesOutput[vertIndex + 3] = rectangleGPUOutput[i].VertexD;

                //Triangles
                trianglesOutput[triIndex]     = vertIndex;
                trianglesOutput[triIndex + 1] = vertIndex + 1;
                trianglesOutput[triIndex + 2] = vertIndex + 2;
                trianglesOutput[triIndex + 3] = vertIndex + 2;
                trianglesOutput[triIndex + 4] = vertIndex + 3;
                trianglesOutput[triIndex + 5] = vertIndex;
            }
            return(verticesOutput, trianglesOutput, fragRegionIndex);
        }