Example #1
0
        internal DetailInstancingDraw(InstancingRenderer renderer, ComputeShader visShader, ComputeShader sortShader,
                                      UnityEngine.Terrain setting, TerrainData data, Vector3 basePos)
            : base(renderer, visShader, sortShader)
        {
            _basePos             = basePos;
            _wavingGrassStrength = data.wavingGrassStrength;

            _wavingTint = data.wavingGrassTint;

            _waveAndDistance.x = 0;
            _waveAndDistance.y = data.wavingGrassSpeed * 0.4f;
            // for mesh grass, should be 0(DetailRenderer.cpp : 288)
            _waveAndDistance.z = data.wavingGrassAmount * 6;
            _waveAndDistance.w = setting.detailObjectDistance * setting.detailObjectDistance;

            _cameraPosition.w = 1 / _waveAndDistance.w;
        }
Example #2
0
        private bool TerrainLoadedInternal(UnityEngine.Terrain setting, float treeDistance, Vector3 basePos,
                                           float[,] heightMap, TextAsset asset)
        {
            var data = setting.terrainData;

            var prototypes     = data.treePrototypes;
            var prototypeCount = prototypes.Length;

            if (prototypeCount == 0)
            {
                _logger.Warn("no tree prototypes exists");
                return(false);
            }

            var heightMapResolution = data.heightmapResolution;
            var division            = (heightMapResolution - 1) / _nodeSize;

            if (!Helper.AlmostEqual(heightMapResolution, division * _nodeSize + 1))
            {
                _logger.WarnFormat("unmatch param in tree: heightMapResolution -> {0}, nodeSize -> {1}, division -> {2}",
                                   heightMapResolution, _nodeSize, division);
                return(false);
            }

            var allTrees   = data.treeInstances;
            var treeCount  = allTrees.Length;
            var nodeMargin = float.MinValue;

            if (_instancingDraw == null)
            {
                _instancingDraw = new TreeInstancingDraw[prototypeCount];
            }

            for (int i = 0; i < prototypeCount; ++i)
            {
                if (_instancingDraw[i] == null)
                {
                    var renderer = new InstancingRenderer(prototypes[i].prefab);
                    nodeMargin         = Mathf.Max(nodeMargin, renderer.SphereRadius);
                    _instancingDraw[i] = new TreeInstancingDraw(renderer, VisibilityShader);
                }
                else
                {
                    nodeMargin = Mathf.Max(nodeMargin, _instancingDraw[i].RendererSphereRadius);
                }
            }

            var nodeSize = new Vector2(data.size.x / division, data.size.z / division);

            _data.SetGridParam(data.size.x, treeDistance, nodeSize);

            var cluster = new GpuInstancingNodeCluster <GpuInstancingTreeNode>();

            cluster.InitDivision(basePos, nodeSize, division, division, treeDistance);
            if (heightMap != null)
            {
                cluster.InitHeightMap(heightMap, data.size.y, nodeMargin);
            }
            else
            {
                // ignore version
                int dataIndex = 6;
                unsafe
                {
                    var     head        = new IntPtr(asset.GetBytesIntPtr().ToInt64() + dataIndex);
                    ushort *flowData    = (ushort *)head.ToPointer();
                    var     detailCount = *flowData;
                    dataIndex += 2 * (1 + detailCount);
                }

                cluster.InitHeightMap(asset, dataIndex, data.size.y, heightMapResolution, nodeMargin);
            }
            cluster.TerrainName = setting.name;

            _terrainProperty = new TerrainProperty();
            _terrainProperty.InitForTree(setting, data, treeDistance, basePos);

            var treeIndex           = new List <int> [division, division][];
            var maxIndex            = division - 1;
            var maxCountInPrototype = new List <int>(prototypeCount);
            var dummy = new List <int> [prototypeCount];

            for (int i = 0; i < prototypeCount; ++i)
            {
                maxCountInPrototype.Add(0);
                dummy[i] = new List <int>();
            }

            for (int i = 0; i < treeCount; ++i)
            {
                var tree = allTrees[i];
                var x    = Mathf.Min(Mathf.FloorToInt(tree.position.x * division), maxIndex);
                var z    = Mathf.Min(Mathf.FloorToInt(tree.position.z * division), maxIndex);

                if (treeIndex[x, z] == null)
                {
                    treeIndex[x, z] = new List <int> [prototypeCount];
                }

                if (treeIndex[x, z][tree.prototypeIndex] == null)
                {
                    treeIndex[x, z][tree.prototypeIndex] = new List <int>();
                }

                treeIndex[x, z][tree.prototypeIndex].Add(i);

                maxCountInPrototype[tree.prototypeIndex] = Mathf.Max(maxCountInPrototype[tree.prototypeIndex], treeIndex[x, z][tree.prototypeIndex].Count);
            }

            for (int x = 0; x < division; ++x)
            {
                for (int z = 0; z < division; ++z)
                {
                    var node = new GpuInstancingTreeNode
                    {
                        TerrainName = setting.name,
                        X           = x,
                        Z           = z
                    };

                    node.SetTreeInstances(treeIndex[x, z] ?? dummy, allTrees);
                    node.SetInstantiationShader(_instantiationShader);
                    node.SetShaderProperty(_terrainProperty);

                    cluster.AddNode(x, z, node);
                }
            }

            cluster.SetMaxCountInLayer(maxCountInPrototype);

            _data.AddCluster(cluster);
            return(true);
        }
        public bool TerrainLoaded(UnityEngine.Terrain setting, float detailDistance)
        {
            var data = setting.terrainData;

            var detailResolution    = data.detailResolution;
            var heightMapResolution = data.heightmapResolution;
            var prototypes          = data.detailPrototypes;
            var detailCount         = prototypes.Length;

            var division = Mathf.CeilToInt(detailResolution / (float)_detailNodeSize);

            if (!Helper.AlmostEqual(detailResolution, division * _detailNodeSize))
            {
                return(false);
            }

            var detailData = new List <int[, ]>();

            if (_instancingDraw == null)
            {
                _instancingDraw = new DetailInstancingDraw[detailCount];
            }

            List <DividedDetailProperty> detailProps = new List <DividedDetailProperty>();

            for (int i = 0; i < detailCount; ++i)
            {
                detailData.Add(data.GetDetailLayer(0, 0, detailResolution, detailResolution, i));
                detailProps.Add(new DividedDetailProperty(data, prototypes[i], _detailNodeSize, i));

                if (_instancingDraw[i] == null)
                {
                    var renderer = new InstancingRenderer(prototypes[i]);
                    _instancingDraw[i] = new DetailInstancingDraw(renderer, VisibilityShader, setting, data);
                }
            }

            var nodeSize = new Vector2(data.size.x / division, data.size.z / division);

            var cluster = new GpuInstancingNodeCluster <GpuInstancingDetailNode>();

            cluster.InitDivision(setting.transform.position, nodeSize, division, division, detailDistance);
            cluster.InitHeightMap(data.GetHeights(0, 0, heightMapResolution, heightMapResolution), data.size.y);

            cluster.TerrainName = setting.name;

            _data.SetGridParam(data.size.x, detailDistance, nodeSize);

            _terrainProperty = new TerrainProperty(setting, data, detailDistance);

            for (int x = 0; x < division; ++x)
            {
                for (int z = 0; z < division; ++z)
                {
                    var node = new GpuInstancingDetailNode();

                    node.TerrainName = setting.name;
                    node.X           = x;
                    node.Z           = z;

                    node.SetInstantiationShader(_instantiationShader);
                    node.SetShaderProperty(_terrainProperty, detailProps);
                    node.InitCountInUnit(detailData, x, z, _detailNodeSize);

                    cluster.AddNode(x, z, node);
                    cluster.UpdateMaxCountInLayer(node);
                }
            }

            _data.AddCluster(cluster);
            return(true);
        }
        public bool TerrainLoaded(TextAsset asset, UnityEngine.Terrain setting, float detailDistance)
        {
            var data = setting.terrainData;
            // ignore version
            int dataIndex = 2;

            int        heightMapResolution = 0;
            int        detailResolution    = 0;
            int        detailCount         = 0;
            List <int> maxCountInLayer     = new List <int>();

            unsafe
            {
                var     head     = new IntPtr(asset.GetBytesIntPtr().ToInt64() + dataIndex);
                ushort *flowData = (ushort *)head.ToPointer();

                heightMapResolution = *flowData++;
                detailResolution    = *flowData++;
                _detailNodeSize     = *flowData++;
                detailCount         = *flowData++;
                for (int i = 0; i < detailCount; ++i)
                {
                    maxCountInLayer.Add(*flowData++);
                }

                dataIndex += 2 * (4 + detailCount);
            }

            var division   = detailResolution / _detailNodeSize;
            var prototypes = data.detailPrototypes;

            if (heightMapResolution != data.heightmapResolution || detailResolution != data.detailResolution ||
                detailCount != prototypes.Length)
            {
                return(false);
            }

            if (_instancingDraw == null)
            {
                _instancingDraw = new DetailInstancingDraw[detailCount];
            }

            List <DividedDetailProperty> detailProps = new List <DividedDetailProperty>();

            for (int i = 0; i < detailCount; ++i)
            {
                detailProps.Add(new DividedDetailProperty(data, prototypes[i], _detailNodeSize, i));

                if (_instancingDraw[i] == null)
                {
                    var renderer = new InstancingRenderer(prototypes[i]);
                    _instancingDraw[i] = new DetailInstancingDraw(renderer, VisibilityShader, setting, data);
                }
            }

            var nodeSize = new Vector2(data.size.x / division, data.size.z / division);

            var cluster = new GpuInstancingNodeCluster <GpuInstancingDetailNode>();

            cluster.InitDivision(setting.transform.position, nodeSize, division, division, detailDistance);
            cluster.InitHeightMap(asset, dataIndex, data.size.y, heightMapResolution);

            cluster.TerrainName = setting.name;

            dataIndex += heightMapResolution * heightMapResolution * 2;

            _data.SetGridParam(data.size.x, detailDistance, nodeSize);

            _terrainProperty = new TerrainProperty(setting, data, detailDistance);
            var layerLength = (detailResolution * detailResolution + division * division) * 2;

            for (int z = 0; z < division; ++z)
            {
                for (int x = 0; x < division; ++x)
                {
                    var node = new GpuInstancingDetailNode();

                    node.TerrainName = setting.name;
                    node.X           = x;
                    node.Z           = z;

                    node.SetInstantiationShader(_instantiationShader);
                    node.SetShaderProperty(_terrainProperty, detailProps);
                    node.InitCountInUnit(x, z, _detailNodeSize, asset, maxCountInLayer, dataIndex, layerLength, division);

                    cluster.AddNode(x, z, node);
                }
            }

            cluster.SetMaxCountInLayer(maxCountInLayer);

            _data.AddCluster(cluster);
            return(true);
        }
 internal TreeInstancingDraw(InstancingRenderer renderer, ComputeShader visShader) : base(renderer, visShader, null)
 {
 }
        public bool TerrainLoaded(UnityEngine.Terrain setting, float detailDistance, Vector3 basePos, float[,] heightMap)
        {
            var data = setting.terrainData;

            var detailResolution = data.detailResolution;
            var prototypes       = data.detailPrototypes;
            var detailCount      = prototypes.Length;

            var division = Mathf.CeilToInt(detailResolution / (float)_nodeSize);

            if (!Helper.AlmostEqual(detailResolution, division * _nodeSize))
            {
                _logger.WarnFormat("unmatch param in detail: detailResolution -> {0}, unitSize -> {1}, division -> {2}",
                                   detailResolution, _nodeSize, division);
                return(false);
            }

            if (detailCount == 0)
            {
                _logger.Warn("no grass prototypes exists");
                return(false);
            }

            var detailData = new List <int[, ]>();

            if (_instancingDraw == null)
            {
                _instancingDraw = new DetailInstancingDraw[detailCount];
            }

            List <DividedDetailProperty> detailProps = new List <DividedDetailProperty>();

            float nodeMargin = float.MinValue;

            for (int i = 0; i < detailCount; ++i)
            {
                detailData.Add(data.GetDetailLayer(0, 0, detailResolution, detailResolution, i));
                detailProps.Add(new DividedDetailProperty(prototypes[i], _nodeSize, i));

                if (_instancingDraw[i] == null)
                {
                    var renderer = new InstancingRenderer(prototypes[i]);
                    nodeMargin         = Mathf.Max(nodeMargin, renderer.SphereRadius);
                    _instancingDraw[i] = new DetailInstancingDraw(renderer, VisibilityShader, SortShader, setting, data, basePos);
                }
            }

            var nodeSize = new Vector2(data.size.x / division, data.size.z / division);

            var cluster = new GpuInstancingNodeCluster <GpuInstancingDetailNode>();

            cluster.InitDivision(basePos, nodeSize, division, division, detailDistance);
            cluster.InitHeightMap(heightMap, data.size.y, nodeMargin);

            cluster.TerrainName = setting.name;

            _data.SetGridParam(data.size.x, detailDistance, nodeSize);

            _terrainProperty = new TerrainProperty();
            _terrainProperty.InitForDetail(setting, data, detailDistance, basePos);

            for (int x = 0; x < division; ++x)
            {
                for (int z = 0; z < division; ++z)
                {
                    var node = new GpuInstancingDetailNode();

                    node.TerrainName = setting.name;
                    node.X           = x;
                    node.Z           = z;

                    node.SetInstantiationShader(_instantiationShader);
                    node.SetShaderProperty(_terrainProperty, detailProps);
                    node.InitCountInUnit(detailData, x, z, _nodeSize);

                    cluster.AddNode(x, z, node);
                    cluster.UpdateMaxCountInLayer(node);
                }
            }

            _data.AddCluster(cluster);
            return(true);
        }
        public bool TerrainLoaded(TextAsset asset, UnityEngine.Terrain setting, float detailDistance, Vector3 basePos)
        {
            var data = setting.terrainData;
            // ignore version
            int dataIndex = 2;

            int        heightMapResolution = 0;
            int        detailResolution    = 0;
            int        detailCount         = 0;
            List <int> maxCountInLayer     = new List <int>();

            unsafe
            {
                var     head     = new IntPtr(asset.GetBytesIntPtr().ToInt64() + dataIndex);
                ushort *flowData = (ushort *)head.ToPointer();

                heightMapResolution = *flowData++;
                detailResolution    = *flowData++;
                _nodeSize           = *flowData++;
                detailCount         = *flowData++;
                for (int i = 0; i < detailCount; ++i)
                {
                    maxCountInLayer.Add(*flowData++);
                }

                dataIndex += 2 * (4 + detailCount);
            }

            var division   = detailResolution / _nodeSize;
            var prototypes = data.detailPrototypes;

            if (heightMapResolution != data.heightmapResolution || detailResolution != data.detailResolution ||
                detailCount != prototypes.Length)
            {
                _logger.WarnFormat("unmatch param in detail: heightMapResolution -> {0}:{1}, detailResolution -> {2}:{3}, detailCount -> {4}:{5}",
                                   data.heightmapResolution, heightMapResolution, data.detailResolution, detailResolution, prototypes.Length, detailCount);
                return(false);
            }

            if (detailCount == 0)
            {
                _logger.Error("no grass prototypes exists");
                return(false);
            }

            if (_instancingDraw == null)
            {
                _instancingDraw = new DetailInstancingDraw[detailCount];
            }

            if (detailCount != _instancingDraw.Length)
            {
                _logger.ErrorFormat("unmatch grass count: unique->{0} other->{1}", detailCount, _instancingDraw);
                return(false);
            }

            List <DividedDetailProperty> detailProps = new List <DividedDetailProperty>();
            float nodeMargin = float.MinValue;

            for (int i = 0; i < detailCount; ++i)
            {
                detailProps.Add(new DividedDetailProperty(prototypes[i], _nodeSize, i));

                if (_instancingDraw[i] == null)
                {
                    var renderer = new InstancingRenderer(prototypes[i]);
                    nodeMargin         = Mathf.Max(nodeMargin, renderer.SphereRadius);
                    _instancingDraw[i] = new DetailInstancingDraw(renderer, VisibilityShader, SortShader, setting, data, basePos);
                }
                else
                {
                    nodeMargin = Mathf.Max(nodeMargin, _instancingDraw[i].RendererSphereRadius);
                }
            }

            var nodeSize = new Vector2(data.size.x / division, data.size.z / division);

            var cluster = new GpuInstancingNodeCluster <GpuInstancingDetailNode>();

            cluster.InitDivision(basePos, nodeSize, division, division, detailDistance);
            cluster.InitHeightMap(asset, dataIndex, data.size.y, heightMapResolution, nodeMargin);

            cluster.TerrainName = setting.name;

            dataIndex += heightMapResolution * heightMapResolution * 2;

            _data.SetGridParam(data.size.x, detailDistance, nodeSize);

            _terrainProperty = new TerrainProperty();
            _terrainProperty.InitForDetail(setting, data, detailDistance, basePos);

            var layerLength = (detailResolution * detailResolution + division * division) * 2;

            for (int z = 0; z < division; ++z)
            {
                for (int x = 0; x < division; ++x)
                {
                    var node = new GpuInstancingDetailNode();

                    node.TerrainName = setting.name;
                    node.X           = x;
                    node.Z           = z;

                    node.SetInstantiationShader(_instantiationShader);
                    node.SetShaderProperty(_terrainProperty, detailProps);
                    node.InitCountInUnit(x, z, _nodeSize, asset, maxCountInLayer, dataIndex, layerLength, division);

                    cluster.AddNode(x, z, node);
                }
            }

            cluster.SetMaxCountInLayer(maxCountInLayer);

            _data.AddCluster(cluster);
            return(true);
        }