コード例 #1
0
        public IEnumerator ReplaceUnityTrees()
        {
            _isCoroutineActive = true;
            if (prototypeList.Count > 0)
            {
                Vector4[] treeScales = new Vector4[prototypeList.Count];
                int       count      = 0;
                foreach (GPUInstancerTreePrototype tp in prototypeList)
                {
                    treeScales[count] = tp.isApplyPrefabScale ? tp.prefabObject.transform.localScale : Vector3.one;
                    count++;
                }
                int[] instanceCounts = new int[prototypeList.Count];

                List <Vector4> treeDataList = new List <Vector4>(); // prototypeIndex - positionx3 - rotation - scalex2

                int instanceTotal = 0;
                foreach (Terrain terrain in _terrains)
                {
                    if (terrain == null)
                    {
                        continue;
                    }
                    if (terrain.terrainData.treePrototypes.Length > prototypeList.Count)
                    {
                        Debug.LogError("Additional Terrain has more Tree protototypes than defined prototypes on the Tree Manager. Tree Manager requires every Terrain to have the same Tree prototypes defined.", terrain);
                        continue;
                    }

                    terrain.treeDistance = 0f; // will not persist if called at runtime.
                    Vector3        terrainSize     = terrain.terrainData.size;
                    Vector3        terrainPosition = terrain.GetPosition();
                    TreeInstance[] treeInstances   = terrain.terrainData.treeInstances;
                    instanceTotal += treeInstances.Length;
                    foreach (TreeInstance treeInstance in treeInstances)
                    {
                        treeDataList.Add(new Vector4(
                                             treeInstance.prototypeIndex,
                                             treeInstance.position.x * terrainSize.x + terrainPosition.x,
                                             treeInstance.position.y * terrainSize.y + terrainPosition.y,
                                             treeInstance.position.z * terrainSize.z + terrainPosition.z
                                             ));

                        treeDataList.Add(new Vector4(
                                             treeInstance.rotation,
                                             treeInstance.widthScale,
                                             treeInstance.heightScale,
                                             0
                                             ));
                        instanceCounts[treeInstance.prototypeIndex]++;
                    }
                }

                if (instanceTotal > 0)
                {
                    if (initializeWithCoroutine && !isInitialized)
                    {
                        yield return(null);
                    }

                    ComputeBuffer treeDataBuffer = new ComputeBuffer(treeDataList.Count, GPUInstancerConstants.STRIDE_SIZE_FLOAT4);
#if UNITY_2019_1_OR_NEWER
                    treeDataBuffer.SetData(treeDataList);
#else
                    treeDataBuffer.SetData(treeDataList.ToArray());
#endif
                    ComputeBuffer treeScalesBuffer = new ComputeBuffer(treeScales.Length, GPUInstancerConstants.STRIDE_SIZE_FLOAT4);
                    treeScalesBuffer.SetData(treeScales);
                    ComputeBuffer counterBuffer    = new ComputeBuffer(1, GPUInstancerConstants.STRIDE_SIZE_INT);
                    uint[]        emptyCounterData = new uint[1];

                    treeDataList = null;
                    treeScales   = null;

                    GPUInstancerRuntimeData runtimeData;
                    for (int i = 0; i < runtimeDataList.Count; i++)
                    {
                        runtimeData = runtimeDataList[i];
                        int instanceCount = instanceCounts[i];
                        runtimeData.bufferSize    = instanceCount;
                        runtimeData.instanceCount = instanceCount;
                        if (instanceCount == 0)
                        {
                            GPUInstancerUtility.ReleaseInstanceBuffers(runtimeData);
                            continue;
                        }

                        counterBuffer.SetData(emptyCounterData);
                        if (runtimeData.transformationMatrixVisibilityBuffer != null)
                        {
                            runtimeData.transformationMatrixVisibilityBuffer.Release();
                        }
                        runtimeData.transformationMatrixVisibilityBuffer = new ComputeBuffer(instanceCount, GPUInstancerConstants.STRIDE_SIZE_MATRIX4X4);

                        _treeInstantiationComputeShader.SetBuffer(0,
                                                                  GPUInstancerConstants.VisibilityKernelPoperties.INSTANCE_DATA_BUFFER, runtimeData.transformationMatrixVisibilityBuffer);
                        _treeInstantiationComputeShader.SetBuffer(0,
                                                                  GPUInstancerConstants.TreeKernelProperties.TREE_DATA, treeDataBuffer);
                        _treeInstantiationComputeShader.SetBuffer(0,
                                                                  GPUInstancerConstants.TreeKernelProperties.TREE_SCALES, treeScalesBuffer);
                        _treeInstantiationComputeShader.SetBuffer(0,
                                                                  GPUInstancerConstants.GrassKernelProperties.COUNTER_BUFFER, counterBuffer);
                        _treeInstantiationComputeShader.SetInt(
                            GPUInstancerConstants.VisibilityKernelPoperties.BUFFER_PARAMETER_BUFFER_SIZE, instanceTotal);
                        //_treeInstantiationComputeShader.SetVector(
                        //    GPUInstancerConstants.GrassKernelProperties.TERRAIN_SIZE_DATA, terrain.terrainData.size);
                        //_treeInstantiationComputeShader.SetVector(
                        //    GPUInstancerConstants.TreeKernelProperties.TERRAIN_POSITION, terrain.GetPosition());
                        _treeInstantiationComputeShader.SetBool(
                            GPUInstancerConstants.TreeKernelProperties.IS_APPLY_ROTATION, ((GPUInstancerTreePrototype)runtimeData.prototype).isApplyRotation);
                        _treeInstantiationComputeShader.SetBool(
                            GPUInstancerConstants.TreeKernelProperties.IS_APPLY_TERRAIN_HEIGHT, ((GPUInstancerTreePrototype)runtimeData.prototype).isApplyTerrainHeight);
                        _treeInstantiationComputeShader.SetInt(
                            GPUInstancerConstants.TreeKernelProperties.PROTOTYPE_INDEX, i);

                        _treeInstantiationComputeShader.Dispatch(0,
                                                                 Mathf.CeilToInt(instanceTotal / GPUInstancerConstants.COMPUTE_SHADER_THREAD_COUNT), 1, 1);

                        GPUInstancerUtility.InitializeGPUBuffer(runtimeData);

                        if (initializeWithCoroutine && !isInitialized)
                        {
                            yield return(null);
                        }
                    }

                    treeDataBuffer.Release();
                    treeScalesBuffer.Release();
                    counterBuffer.Release();
                }
                else
                {
                    GPUInstancerUtility.ReleaseInstanceBuffers(runtimeDataList);
                }
            }

            isInitial = true;
            if (!isInitialized)
            {
                GPUInstancerUtility.TriggerEvent(GPUInstancerEventType.TreeInitializationFinished);
            }
            _isCoroutineActive = false;
        }
コード例 #2
0
        public IEnumerator ReplaceUnityTrees()
        {
            TreeInstance[] treeInstances = terrain.terrainData.treeInstances;
            int            instanceTotal = treeInstances.Length;

            if (instanceTotal > 0)
            {
                Vector3 terrainSize     = terrain.terrainData.size;
                Vector3 terrainPosition = terrain.GetPosition();

                Vector3      treePos = Vector3.zero;
                TreeInstance treeInstance;

                Vector4[] treeScales = new Vector4[prototypeList.Count];
                int       count      = 0;
                foreach (GPUInstancerTreePrototype tp in prototypeList)
                {
                    treeScales[count] = tp.prefabObject.transform.localScale;
                    count++;
                }

                terrain.treeDistance = 0f;                                 // will not persist if called at runtime.

                Vector4[] treeDataArray  = new Vector4[instanceTotal * 2]; // prototypeIndex - positionx3 - rotation - scalex2
                int[]     instanceCounts = new int[terrain.terrainData.treePrototypes.Length];

                int index = 0;
                for (int i = 0; i < instanceTotal; i++)
                {
                    treeInstance = treeInstances[i];
                    treePos      = treeInstance.position;

                    treeDataArray[index].x = treeInstance.prototypeIndex;
                    treeDataArray[index].y = treePos.x;
                    treeDataArray[index].z = treePos.y;
                    treeDataArray[index].w = treePos.z;
                    index++;
                    treeDataArray[index].x = treeInstance.rotation;
                    treeDataArray[index].y = treeInstance.widthScale;
                    treeDataArray[index].z = treeInstance.heightScale;
                    index++;

                    instanceCounts[treeInstance.prototypeIndex]++;
                }
                yield return(null);

                ComputeBuffer treeDataBuffer = new ComputeBuffer(treeDataArray.Length, GPUInstancerConstants.STRIDE_SIZE_FLOAT4);
                treeDataBuffer.SetData(treeDataArray);
                ComputeBuffer treeScalesBuffer = new ComputeBuffer(treeScales.Length, GPUInstancerConstants.STRIDE_SIZE_FLOAT4);
                treeScalesBuffer.SetData(treeScales);
                ComputeBuffer counterBuffer    = new ComputeBuffer(1, GPUInstancerConstants.STRIDE_SIZE_INT);
                uint[]        emptyCounterData = new uint[1];

                GPUInstancerRuntimeData runtimeData;
                for (int i = 0; i < runtimeDataList.Count; i++)
                {
                    if (instanceCounts[i] == 0)
                    {
                        continue;
                    }

                    runtimeData = runtimeDataList[i];

                    counterBuffer.SetData(emptyCounterData);
                    runtimeData.transformationMatrixVisibilityBuffer = new ComputeBuffer(instanceCounts[i], GPUInstancerConstants.STRIDE_SIZE_MATRIX4X4);

                    _treeInstantiationComputeShader.SetBuffer(0,
                                                              GPUInstancerConstants.VisibilityKernelPoperties.INSTANCE_DATA_BUFFER, runtimeData.transformationMatrixVisibilityBuffer);
                    _treeInstantiationComputeShader.SetBuffer(0,
                                                              GPUInstancerConstants.TreeKernelProperties.TREE_DATA, treeDataBuffer);
                    _treeInstantiationComputeShader.SetBuffer(0,
                                                              GPUInstancerConstants.TreeKernelProperties.TREE_SCALES, treeScalesBuffer);
                    _treeInstantiationComputeShader.SetBuffer(0,
                                                              GPUInstancerConstants.GrassKernelProperties.COUNTER_BUFFER, counterBuffer);
                    _treeInstantiationComputeShader.SetInt(
                        GPUInstancerConstants.VisibilityKernelPoperties.BUFFER_PARAMETER_BUFFER_SIZE, instanceTotal);
                    _treeInstantiationComputeShader.SetVector(
                        GPUInstancerConstants.GrassKernelProperties.TERRAIN_SIZE_DATA, terrainSize);
                    _treeInstantiationComputeShader.SetVector(
                        GPUInstancerConstants.TreeKernelProperties.TERRAIN_POSITION, terrainPosition);
                    _treeInstantiationComputeShader.SetBool(
                        GPUInstancerConstants.TreeKernelProperties.IS_APPLY_ROTATION, ((GPUInstancerTreePrototype)runtimeData.prototype).isApplyRotation);
                    _treeInstantiationComputeShader.SetInt(
                        GPUInstancerConstants.TreeKernelProperties.PROTOTYPE_INDEX, i);

                    _treeInstantiationComputeShader.Dispatch(0,
                                                             Mathf.CeilToInt(instanceTotal / GPUInstancerConstants.VISIBILITY_SHADER_THREAD_COUNT), 1, 1);

                    runtimeData.bufferSize    = instanceCounts[i];
                    runtimeData.instanceCount = instanceCounts[i];
                    GPUInstancerUtility.InitializeGPUBuffer(runtimeData);

                    yield return(null);
                }

                treeDataBuffer.Release();
                treeScalesBuffer.Release();
                counterBuffer.Release();
            }

            isInitial = true;
            GPUInstancerUtility.TriggerEvent(GPUInstancerEventType.TreeInitializationFinished);
        }