Пример #1
0
    /// <summary>
    /// Computes the grass mesh for [Billboard-set Grass System].
    /// </summary>
    /// <returns>
    /// Offset in 'grass_list' from where you can compute the next mesh.
    /// </returns>
    /// <param name='grass_list'>
    /// The grass instance list.
    /// </param>
    /// <param name='offset'>
    /// Offset in 'grass_list' from where you compute the mesh.
    /// </param>
    /// <param name='mf_inout'>
    /// [inout] The MeshFilter component receives the mesh.
    /// </param>
    public static int ComputeMesh(List <GrassInstance> grass_list, int offset, MeshFilter mf_inout)
    {
        if (grass_list == null)
        {
            return(0);
        }
        offset = Mathf.Clamp(offset, 0, grass_list.Count);
        int grasspermesh = Mathf.Clamp(s_GrassCountPerMesh, 128, 16240);
        int grasscount   = Mathf.Min(grasspermesh, grass_list.Count - offset);

        if (grasscount < 1)
        {
            return(grass_list.Count);
        }
        if (mf_inout == null)
        {
            return(grass_list.Count);
        }

        Vector3[] verts    = new Vector3 [grasscount << 2];
        Vector3[] norms    = new Vector3 [grasscount << 2];
        Vector2[] uvs      = new Vector2 [grasscount << 2];
        Vector2[] uv2s     = new Vector2 [grasscount << 2];
        Color32[] colors32 = new Color32 [grasscount << 2];
        int[]     indices  = new int [grasscount * 6];

        Vector3 A  = new Vector3(-1, -1, 0);
        Vector3 B  = new Vector3(-1, 1, 0);
        Vector3 C  = new Vector3(1, 1, 0);
        Vector3 D  = new Vector3(1, -1, 0);
        Vector3 up = Vector3.up;

        for (int i = 0; i < grasscount; ++i)
        {
            int a = i * 4;
            int b = a + 1;
            int c = a + 2;
            int d = a + 3;

            indices[i * 6 + 0] = a;
            indices[i * 6 + 1] = b;
            indices[i * 6 + 2] = c;
            indices[i * 6 + 3] = c;
            indices[i * 6 + 4] = d;
            indices[i * 6 + 5] = a;

            verts[a] = A;
            verts[b] = B;
            verts[c] = C;
            verts[d] = D;

            GrassInstance gi = grass_list[offset + i];

            norms[d] = norms[c] = norms[b] = norms[a] = gi.Position;

            Vector3 n  = gi.Normal;
            Vector3 n1 = (n * 1.25f - up * 0.25f).normalized;
            Vector3 n2 = (n * 0.5f + up * 0.5f).normalized;

            uvs[a] = new Vector2(n1.x, n1.z);
            uvs[c] = uvs[b] = new Vector2(n2.x, n2.z);
            uvs[d] = uvs[a];

            uv2s[d] = uv2s[c] = uv2s[b] = uv2s[a] = new Vector2((float)(gi.Prototype) / (float)(GrassPrototypeMgr.s_PrototypeCount), 0);

            colors32[d] = colors32[c] = colors32[b] = colors32[a] = gi.ColorDw;
        }

        Mesh mesh = mf_inout.mesh;

        mesh.Clear();
        mesh.vertices  = verts;
        mesh.triangles = indices;
        mesh.normals   = norms;
        mesh.uv        = uvs;
        mesh.uv2       = uv2s;
        mesh.colors32  = colors32;

        return(offset + grasscount);
    }
Пример #2
0
    /// <summary>
    /// Computes the grass mesh for [Billboard-set Tri-grass System].
    /// </summary>
    /// <returns>
    /// Offset in 'grass_list' from where you can compute the next mesh.
    /// </returns>
    /// <param name='grass_list'>
    /// The grass instance list.
    /// </param>
    /// <param name='offset'>
    /// Offset in 'grass_list' from where you compute the mesh.
    /// </param>
    /// <param name='mf_inout'>
    /// [inout] The MeshFilter component receives the mesh.
    /// </param>
    public static int ComputeMesh(List <GrassInstance> grass_list, int offset, MeshFilter mf_inout)
    {
        //Win32.HiPerfTimer hitimer = new Win32.HiPerfTimer ();
        //hitimer.Start();
        if (grass_list == null)
        {
            return(0);
        }
        offset = Mathf.Clamp(offset, 0, grass_list.Count);
        int grasspermesh = Mathf.Clamp(s_GrassCountPerMesh, 128, 5400);
        int grasscount   = Mathf.Min(grasspermesh, grass_list.Count - offset);

        if (grasscount < 1)
        {
            return(grass_list.Count);
        }
        if (mf_inout == null)
        {
            return(grass_list.Count);
        }

        Vector3[] verts    = new Vector3 [grasscount * 12];
        Vector3[] norms    = new Vector3 [grasscount * 12];
        Vector2[] uvs      = new Vector2 [grasscount * 12];
        Vector2[] uv2s     = new Vector2 [grasscount * 12];
        Color32[] colors32 = new Color32 [grasscount * 12];
        int[]     indices  = new int [grasscount * 18];

        Vector3 A  = new Vector3(-1, -1, 0);
        Vector3 B  = new Vector3(-1, 1, 0);
        Vector3 C  = new Vector3(1, 1, 0);
        Vector3 D  = new Vector3(1, -1, 0);
        Vector3 up = Vector3.up;

        float _2pi           = Mathf.PI * 2;
        float _page_interval = _2pi / 3;

        float angle_randomness = 0.3f;

//		float size_randomness = 0.3f;
//		float min_size = 0.85f;
//		float bias_randomness = 0.3f;
//		float min_bias = 0.1f;
//		float side_randomness = 2f;

        for (int i = 0; i < grasscount; ++i)
        {
            float phase = Random.value * _2pi;

            for (int p = 0; p < 3; ++p)
            {
//				float angle = angle_randomness * (Random.value - 0.5f) + p*_page_interval + phase;
//				float height = min_size + Random.value * size_randomness;
//				float width = min_size + Random.value * size_randomness;
//				float bias = Random.value * bias_randomness + min_bias;
//				float side = (Random.value - 0.5f) * side_randomness;
//
//				float cos = width*Mathf.Cos(angle);
//				float sin = width*Mathf.Sin(angle);
//				float bias_x_up = (-sin*bias) * (1+side);
//				float bias_z_up = (cos*bias) * (1+side);
//				float bias_x_dn = (-sin*bias) * (1-side);
//				float bias_z_dn = (cos*bias) * (1-side);
//
//				Vector3 A = new Vector3 (-cos + bias_x_dn, -height, -sin + bias_z_dn);
//				Vector3 B = new Vector3 (-cos + bias_x_up,  height, -sin + bias_z_up);
//				Vector3 C = new Vector3 ( cos + bias_x_up,  height,  sin + bias_z_up);
//				Vector3 D = new Vector3 ( cos + bias_x_dn, -height,  sin + bias_z_dn);

                int a = i * 12 + p * 4;
                int b = a + 1;
                int c = a + 2;
                int d = a + 3;

                int idx = i * 18 + p * 6;

                indices[idx + 0] = a;
                indices[idx + 1] = b;
                indices[idx + 2] = c;
                indices[idx + 3] = c;
                indices[idx + 4] = d;
                indices[idx + 5] = a;

                verts[a] = A;
                verts[b] = B;
                verts[c] = C;
                verts[d] = D;

                GrassInstance gi = grass_list[offset + i];

                norms[d] = norms[c] = norms[b] = norms[a] = gi.Position;

                Vector3 n  = gi.Normal;
                Vector3 n1 = (n * 1.1f - up * 0.1f).normalized;
                Vector3 n2 = (n * 0.5f + up * 0.5f).normalized;

                uvs[a] = new Vector2(n1.x, n1.z);
                uvs[c] = uvs[b] = new Vector2(n2.x, n2.z);
                uvs[d] = uvs[a];

                uv2s[d] = uv2s[c] = uv2s[b] = uv2s[a] = new Vector2((float)(gi.Prototype) / (float)(GrassPrototypeMgr.s_PrototypeCount),
                                                                    p * _page_interval + phase + (Random.value - 0.5f) * angle_randomness);

                colors32[d] = colors32[c] = colors32[b] = colors32[a] = gi.ColorDw;
            }
        }

        Mesh mesh = mf_inout.mesh;

        mesh.Clear();
        mesh.vertices  = verts;
        mesh.triangles = indices;
        mesh.normals   = norms;
        mesh.uv        = uvs;
        mesh.uv2       = uv2s;
        mesh.colors32  = colors32;

        //hitimer.Stop();
        //hitimer.PrintDuration("Compute Mesh");

        return(offset + grasscount);
    }
Пример #3
0
    void ReGen()
    {
        m_Grasses.Clear();
        SimplexNoise noise = new SimplexNoise();
        //Random.seed = Time.frameCount + Mathf.RoundToInt(Random.value*1000000);
        RaycastHit rch;

        for (int i = 0; i < m_GrassCount; i++)
        {
            Vector3 origin = new Vector3(Random.value, 1, Random.value) * m_GenAreaSize + m_StartCoord;
//			IntVector3 origin_i = new IntVector3(origin);
//			int hash = origin_i.GetHashCode();
//
//			if ( !m_map.ContainsKey(hash) )
//				m_map.Add(hash, new List<GrassInstance>());
//			if ( m_map[hash].Count > 1 )
//			{
//				float p = Mathf.Pow(0.7f, (float)(m_map[hash].Count));
//				if ( Random.value > p )
//					continue;
//			}

            origin.y = 512f;

            if (Physics.Raycast(origin, Vector3.down, out rch, 1024, 1 << Pathea.Layer.VFVoxelTerrain))
            {
                float nx = (float)(noise.Noise(rch.point.x / 32, rch.point.y / 32, rch.point.z / 32)) + 1;
                float ny = (float)(noise.Noise((rch.point.x + m_GenAreaSize) / 32, (rch.point.y + m_GenAreaSize) / 32, (rch.point.z + m_GenAreaSize) / 32)) + 1;
                float nz = (float)(noise.Noise(rch.point.y / 16, rch.point.z / 16, rch.point.x / 16)) + 1;

                nx = Mathf.Pow(nx, 15);
                ny = Mathf.Pow(ny, 15);
                nz = Mathf.Pow(nz, 15);

                float sum = nx + ny + nz;
                nx /= sum;
                ny /= sum; ny += nx;
                nz /= sum; nz += ny;

                GrassInstance gi = new GrassInstance();
                gi.Position = rch.point;
                gi.Normal   = rch.normal;
                gi.ColorF   = m_GrassColor;

                float r = Random.value;
                if (r < nx)
                {
                    gi.Prototype = m_ProtoType0;
                }
                else if (r < ny)
                {
                    gi.Prototype = m_ProtoType1;
                }
                else if (r < nz)
                {
                    gi.Prototype = m_ProtoType2;
                }

                m_Grasses.Add(gi);
//				m_map[hash].Add(gi);
            }
        }

        TrigrassMeshComputer.ComputeMesh(m_Grasses, 0, m_Mesh);
        m_Grasses.Clear();
    }
    static void SplatOcclusion(GrassPrototype grassPrototype, TreeInstance[] instances, TreePrototype[] prototypes, Material material, float terrainScale, bool nonTerrainInstances, Matrix4x4 worldToLocal)
    {
        if (!grassPrototype.m_Use)
        {
            return;
        }

        int instanceCount = 0;

        foreach (TreeInstance ti in instances)
        {
            if (prototypes[ti.prototypeIndex].prefab == grassPrototype.m_Prefab)
            {
                instanceCount++;
            }
        }

        List <GameObject> manualInstances = null;

        if (nonTerrainInstances)
        {
            manualInstances = FindAllPrefabInstances(grassPrototype.m_Prefab);
            instanceCount  += manualInstances.Count;
        }

        if (instanceCount == 0)
        {
            return;
        }

        GrassInstance[] grassInstances = new GrassInstance[instanceCount];

        Bounds bounds = grassPrototype.m_Prefab.GetComponent <LODGroup>().GetLODs()[0].renderers[0].GetComponent <MeshFilter>().sharedMesh.bounds;
        float  sizex  = bounds.extents.x + Mathf.Abs(bounds.center.x);
        float  sizez  = bounds.extents.z + Mathf.Abs(bounds.center.z);
        float  size   = Mathf.Max(sizex * grassPrototype.m_Prefab.transform.localScale.x, sizez * grassPrototype.m_Prefab.transform.localScale.z);

        size *= terrainScale;

        int i = 0;

        foreach (TreeInstance inst in instances)
        {
            //TreePrototype prototype = prototypes[ti.prototypeIndex];
            if (prototypes[inst.prototypeIndex].prefab != grassPrototype.m_Prefab)
            {
                continue;
            }

            GrassInstance grassInstance = new GrassInstance();

            Vector3 pos = inst.position;
            grassInstance.position = new Vector2(pos.x, pos.z);

            grassInstance.scale = inst.widthScale * size;

            grassInstance.rotation = inst.rotation;

            grassInstances[i] = grassInstance;

            i++;
        }

        if (nonTerrainInstances && manualInstances != null && manualInstances.Count > 0)
        {
            foreach (GameObject inst in manualInstances)
            {
                GrassInstance grassInstance = new GrassInstance();

                Vector3 pos = inst.transform.position;
                pos = worldToLocal.MultiplyPoint3x4(pos);
                grassInstance.position = new Vector2(pos.x, pos.z);

                grassInstance.scale = inst.transform.localScale.x * size;

                grassInstance.rotation = inst.transform.rotation.eulerAngles.y * Mathf.Deg2Rad;

                grassInstances[i] = grassInstance;

                i++;
            }
        }

        ComputeBuffer grassInstancesCB = new ComputeBuffer(instanceCount, 16);

        grassInstancesCB.SetData(grassInstances);
        material.SetBuffer(UniformsBake._Instances, grassInstancesCB);

        Vector2[]     verts     = new Vector2[] { new Vector2(-1, -1), new Vector2(1, -1), new Vector2(1, 1), new Vector2(-1, -1), new Vector2(1, 1), new Vector2(-1, 1) };
        int           vertCount = verts.Length;
        ComputeBuffer vertsCB   = new ComputeBuffer(vertCount, 8);

        vertsCB.SetData(verts);
        material.SetBuffer(UniformsBake._Verts, vertsCB);

        material.SetTexture(UniformsBake._Occlusion, grassPrototype.m_Occlusion);
        material.SetFloat(UniformsBake._Bias, grassPrototype.m_Bias);
        material.SetPass(0);

        Graphics.DrawProcedural(MeshTopology.Triangles, vertCount, instanceCount);
        vertsCB.Release();
    }
Пример #5
0
        public void Init()
        {
            var timeNow = DateTime.Now;

            Debug.Log("##### Start preparing simulation #####");

            if (Settings == null)
            {
                Settings = new SimulationSettings();
            }
            if (EditorSettings == null)
            {
                EditorSettings = new EditorSettings();
            }
            if (CollisionCamera == null)
            {
                CollisionCamera = GameObject.FindWithTag("GrassSimulationCollisionCamera").GetComponent <Camera>();
            }
            if (BillboardTextureCamera == null)
            {
                BillboardTextureCamera = GameObject.FindWithTag("BillboardTextureCamera").GetComponent <Camera>();
            }
            BillboardTexturePatchContainer = null;
            BillboardTexturePatchContainer = CreateInstance <BillboardTexturePatchContainer>();

            if (BladeContainer == null)
            {
                BladeContainer = CreateInstance <BladeContainer>();
            }
            BladeContainer.Init(this);
            BlossomCount = BladeContainer.GetBlossomCount();
            var timeTextureArrays = DateTime.Now;

            BladeTexture2DArray0   = BladeContainer.GetGeoemetryTexture2DArray(0);
            BladeTexture2DArray1   = BladeContainer.GetGeoemetryTexture2DArray(2);
            BlossomTexture2DArray0 = BladeContainer.GetGeoemetryTexture2DArray(1);
            BlossomTexture2DArray1 = BladeContainer.GetGeoemetryTexture2DArray(3);
            Debug.Log("\t Created Texture Arrays for LookUp- and Surface-Textures for " + BladeContainer.Blades.Length + " Blades and " + BlossomCount + " Blossoms in " + (int)(DateTime.Now - timeTextureArrays).TotalMilliseconds + "ms");
            if (!Transform || !Camera || !CollisionCamera || !BillboardTextureCamera || !GrassSimulationComputeShader || !CollisionDepthShader || !GrassSimulationShader || !DimensionsInput || !GrassMapInput || !HeightInput || !NormalInput || !PositionInput || !PatchContainer || BladeTexture2DArray0 == null || BladeTexture2DArray1 == null)
            {
                Debug.LogWarning("GrassSimulation: Not all dependencies are set.");
                if (!Transform)
                {
                    Debug.Log("GrassSimulation: Transform not set.");
                }
                if (!Camera)
                {
                    Debug.Log("GrassSimulation: Camera not set.");
                }
                if (!CollisionCamera)
                {
                    Debug.Log("GrassSimulation: Could not find Camera on GameObject with Tag GrassSimulationCollisionCamera");
                }
                if (!BillboardTextureCamera)
                {
                    Debug.Log("GrassSimulation: Could not find Camera on GameObject with Tag BillboardTextureCamera");
                }
                if (!GrassSimulationComputeShader)
                {
                    Debug.Log("GrassSimulation: GrassSimulationComputeShader not set.");
                }
                if (!CollisionDepthShader)
                {
                    Debug.Log("GrassSimulation: CollisionDepthShader not set.");
                }
                if (!GrassSimulationShader)
                {
                    Debug.Log("GrassSimulation: GrassSimulationShader not set.");
                }
                if (!DimensionsInput)
                {
                    Debug.Log("GrassSimulation: DimensionsInput not set.");
                }
                if (!GrassMapInput)
                {
                    Debug.Log("GrassSimulation: GrassMapInput not set.");
                }
                if (!HeightInput)
                {
                    Debug.Log("GrassSimulation: HeightInput not set.");
                }
                if (!NormalInput)
                {
                    Debug.Log("GrassSimulation: NormalInput not set.");
                }
                if (!PositionInput)
                {
                    Debug.Log("GrassSimulation: PositionInput not set.");
                }
                if (!PatchContainer)
                {
                    Debug.Log("GrassSimulation: PatchContainer not set.");
                }
                if (BladeTexture2DArray0 == null || BladeTexture2DArray1 == null)
                {
                    Debug.Log("GrassSimulation: No Grass Blades set. Cannot create Textures.");
                }
                IsReady = false;
                return;
            }

            //Create a single random object
            Random = new Random(Settings.RandomSeed);

            //Find kernels for ComputeShaders
            KernelPhysics         = GrassSimulationComputeShader.FindKernel("PhysicsMain");
            KernelSimulationSetup = GrassSimulationComputeShader.FindKernel("SimulationSetup");

            //Create Material Variants

            GrassGeometry            = new Material(GrassSimulationShader);
            GrassBillboardGeneration = new Material(GrassGeometry);
            GrassBillboardCrossed    = new Material(GrassGeometry);
            GrassBillboardScreen     = new Material(GrassGeometry);


            //if (BlossomCount > 0)
            //{
            GrassBlossom = new Material(GrassGeometry);
            GrassBlossomBillboardGeneration = new Material(GrassGeometry);
            GrassBlossom.EnableKeyword("GRASS_BLOSSOM");
            GrassBlossom.DisableKeyword("GRASS_GEOMETRY");
            GrassBlossom.DisableKeyword("GRASS_BILLBOARD_CROSSED");
            GrassBlossom.DisableKeyword("GRASS_BILLBOARD_SCREEN");
            GrassBlossom.SetTexture("GrassBlossom0", BlossomTexture2DArray0);
            GrassBlossom.SetTexture("GrassBlossom1", BlossomTexture2DArray1);
            GrassBlossom.SetInt("EnableHeightTransition", Settings.EnableHeightTransition ? 1 : 0);
            GrassBlossom.SetInt("VertexCount", (int)Settings.GetMinAmountBladesPerPatch());
            GrassBlossom.SetInt("BlossomCount", BlossomCount);
            GrassBlossom.SetFloat("BladeTextureMaxMipmapLevel", Settings.BladeTextureMaxMipmapLevel);
            GrassBlossom.SetFloat("BladeHeightCullingThreshold", Settings.BladeHeightCullingThreshold);
            GrassBlossom.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassBlossom.SetFloat("LodInstancesGeometry",
                                  Settings.LodInstancesGeometry / (float)Settings.LodGeometryTransitionSegments);
            GrassBlossom.SetFloat("LodGeometryTransitionSegments", Settings.LodGeometryTransitionSegments);
            GrassBlossom.SetFloat("LodDistanceGeometryStart", Settings.LodDistanceGeometryStart);
            GrassBlossom.SetFloat("LodDistanceGeometryEnd", Settings.LodDistanceGeometryEnd);
            GrassBlossom.SetFloat("LodTessellationMin", Settings.LodTessellationMin);
            GrassBlossom.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassBlossom.SetFloat("LodDistanceTessellationMin", Settings.LodDistanceTessellationMin);
            GrassBlossom.SetFloat("LodDistanceTessellationMax", Settings.LodDistanceTessellationMax);

            GrassBlossomBillboardGeneration.EnableKeyword("BILLBOARD_GENERATION");
            GrassBlossomBillboardGeneration.EnableKeyword("GRASS_BLOSSOM");
            GrassBlossomBillboardGeneration.DisableKeyword("GRASS_GEOMETRY");
            GrassBlossomBillboardGeneration.DisableKeyword("GRASS_BILLBOARD_CROSSED");
            GrassBlossomBillboardGeneration.DisableKeyword("GRASS_BILLBOARD_SCREEN");
            GrassBlossomBillboardGeneration.SetTexture("GrassBlossom0", BlossomTexture2DArray0);
            GrassBlossomBillboardGeneration.SetTexture("GrassBlossom1", BlossomTexture2DArray1);
            GrassBlossomBillboardGeneration.SetInt("EnableHeightTransition", Settings.EnableHeightTransition ? 1 : 0);
            GrassBlossomBillboardGeneration.SetInt("VertexCount", (int)Settings.BillboardGrassCount);
            GrassBlossomBillboardGeneration.SetInt("BlossomCount", BlossomCount);
            GrassBlossomBillboardGeneration.SetFloat("BladeTextureMaxMipmapLevel", Settings.BladeTextureMaxMipmapLevel);
            GrassBlossomBillboardGeneration.SetFloat("BladeHeightCullingThreshold", Settings.BladeHeightCullingThreshold);
            GrassBlossomBillboardGeneration.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassBlossomBillboardGeneration.SetFloat("LodInstancesGeometry",
                                                     Settings.LodInstancesGeometry / (float)Settings.LodGeometryTransitionSegments);
            GrassBlossomBillboardGeneration.SetFloat("LodGeometryTransitionSegments", Settings.LodGeometryTransitionSegments);
            //GrassBlossomBillboardGeneration.SetFloat("LodDistanceGeometryStart", 0);
            GrassBlossomBillboardGeneration.SetFloat("LodDistanceGeometryStart", 1);
            GrassBlossomBillboardGeneration.SetFloat("LodDistanceGeometryEnd", 100);
            GrassBlossomBillboardGeneration.SetFloat("LodTessellationMin", Settings.LodTessellationMin);
            GrassBlossomBillboardGeneration.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassBlossomBillboardGeneration.SetFloat("LodDistanceTessellationMin", Settings.LodDistanceTessellationMin);
            GrassBlossomBillboardGeneration.SetFloat("LodDistanceTessellationMax", Settings.LodDistanceTessellationMax);

            /*} else
             * {
             *      GrassBlossom = null;
             *      GrassBlossomBillboardGeneration = null;
             * }*/

            GrassGeometry.EnableKeyword("GRASS_GEOMETRY");
            GrassGeometry.DisableKeyword("GRASS_BLOSSOM");
            GrassGeometry.DisableKeyword("GRASS_BILLBOARD_CROSSED");
            GrassGeometry.DisableKeyword("GRASS_BILLBOARD_SCREEN");
            GrassGeometry.SetTexture("GrassBlades0", BladeTexture2DArray0);
            GrassGeometry.SetTexture("GrassBlades1", BladeTexture2DArray1);
            GrassGeometry.SetInt("EnableHeightTransition", Settings.EnableHeightTransition ? 1 : 0);
            GrassGeometry.SetInt("VertexCount", (int)Settings.GetMinAmountBladesPerPatch());
            GrassGeometry.SetFloat("BladeTextureMaxMipmapLevel", Settings.BladeTextureMaxMipmapLevel);
            GrassGeometry.SetFloat("BladeHeightCullingThreshold", Settings.BladeHeightCullingThreshold);
            GrassGeometry.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassGeometry.SetFloat("LodInstancesGeometry", Settings.LodInstancesGeometry / (float)Settings.LodGeometryTransitionSegments);
            GrassGeometry.SetFloat("LodGeometryTransitionSegments", Settings.LodGeometryTransitionSegments);
            GrassGeometry.SetFloat("LodDistanceGeometryStart", Settings.LodDistanceGeometryStart);
            GrassGeometry.SetFloat("LodDistanceGeometryEnd", Settings.LodDistanceGeometryEnd);
            GrassGeometry.SetFloat("LodTessellationMin", Settings.LodTessellationMin);
            GrassGeometry.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassGeometry.SetFloat("LodDistanceTessellationMin", Settings.LodDistanceTessellationMin);
            GrassGeometry.SetFloat("LodDistanceTessellationMax", Settings.LodDistanceTessellationMax);

            GrassBillboardGeneration.EnableKeyword("BILLBOARD_GENERATION");
            GrassBillboardGeneration.EnableKeyword("GRASS_GEOMETRY");
            GrassBillboardGeneration.DisableKeyword("GRASS_BLOSSOM");
            GrassBillboardGeneration.DisableKeyword("GRASS_BILLBOARD_CROSSED");
            GrassBillboardGeneration.DisableKeyword("GRASS_BILLBOARD_SCREEN");
            GrassBillboardGeneration.SetTexture("GrassBlades0", BladeTexture2DArray0);
            GrassBillboardGeneration.SetTexture("GrassBlades1", BladeTexture2DArray1);
            GrassBillboardGeneration.SetInt("EnableHeightTransition", Settings.EnableHeightTransition ? 1 : 0);
            GrassBillboardGeneration.SetInt("VertexCount", (int)Settings.BillboardGrassCount);
            GrassBillboardGeneration.SetFloat("BladeTextureMaxMipmapLevel", Settings.BladeTextureMaxMipmapLevel);
            GrassBillboardGeneration.SetFloat("BladeHeightCullingThreshold", Settings.BladeHeightCullingThreshold);
            GrassBillboardGeneration.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassBillboardGeneration.SetFloat("LodInstancesGeometry", Settings.LodInstancesGeometry / (float)Settings.LodGeometryTransitionSegments);
            GrassBillboardGeneration.SetFloat("LodGeometryTransitionSegments", Settings.LodGeometryTransitionSegments);
            //GrassBillboardGeneration.SetFloat("LodDistanceGeometryStart", 0);
            GrassBillboardGeneration.SetFloat("LodDistanceGeometryStart", 1);
            GrassBillboardGeneration.SetFloat("LodDistanceGeometryEnd", 100);
            GrassBillboardGeneration.SetFloat("LodTessellationMin", Settings.LodTessellationMin);
            GrassBillboardGeneration.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassBillboardGeneration.SetFloat("LodDistanceTessellationMin", Settings.LodDistanceTessellationMin);
            GrassBillboardGeneration.SetFloat("LodDistanceTessellationMax", Settings.LodDistanceTessellationMax);

            GrassBillboardCrossed.SetOverrideTag("Queue", "AlphaTest");
            GrassBillboardCrossed.SetOverrideTag("RenderType", "TransparentCutout");
            GrassBillboardCrossed.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
            GrassBillboardCrossed.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            //GrassBillboardCrossed.SetInt("_ZWrite", 0);
            GrassBillboardCrossed.SetInt("_AlphaToMask", 1);
            GrassBillboardCrossed.renderQueue = 3000;
            GrassBillboardCrossed.DisableKeyword("GRASS_GEOMETRY");
            GrassBillboardCrossed.DisableKeyword("GRASS_BLOSSOM");
            GrassBillboardCrossed.EnableKeyword("GRASS_BILLBOARD_CROSSED");
            GrassBillboardCrossed.DisableKeyword("GRASS_BILLBOARD_SCREEN");
            GrassBillboardCrossed.SetTexture("GrassBlades0", BladeTexture2DArray0);
            GrassBillboardCrossed.SetInt("EnableHeightTransition", Settings.EnableHeightTransition ? 1 : 0);
            GrassBillboardCrossed.SetInt("VertexCount", (int)Settings.GetMinAmountBillboardsPerPatch());
            GrassBillboardCrossed.SetFloat("BillboardAlphaCutoff", Settings.BillboardAlphaCutoff);
            GrassBillboardCrossed.SetFloat("BillboardHeightAdjustment", Settings.BillboardHeightAdjustment);
            GrassBillboardCrossed.SetFloat("BladeHeightCullingThreshold", Settings.BladeHeightCullingThreshold);
            GrassBillboardCrossed.SetFloat("LodInstancesBillboardCrossed", Settings.LodInstancesBillboardCrossed / (float)Settings.LodBillboardCrossedTransitionSegments);
            GrassBillboardCrossed.SetFloat("LodBillboardCrossedTransitionSegments", Settings.LodBillboardCrossedTransitionSegments);
            GrassBillboardCrossed.SetFloat("LodDistanceBillboardCrossedStart", Settings.LodDistanceBillboardCrossedStart);
            GrassBillboardCrossed.SetFloat("LodDistanceBillboardCrossedPeak", Settings.LodDistanceBillboardCrossedPeak);
            GrassBillboardCrossed.SetFloat("LodDistanceBillboardCrossedEnd", Settings.LodDistanceBillboardCrossedEnd);

            GrassBillboardScreen.SetOverrideTag("Queue", "AlphaTest");
            GrassBillboardScreen.SetOverrideTag("RenderType", "TransparentCutout");
            GrassBillboardScreen.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
            GrassBillboardScreen.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            //GrassBillboardScreen.SetInt("_ZWrite", 0);
            GrassBillboardScreen.SetInt("_AlphaToMask", 1);
            GrassBillboardScreen.renderQueue = 2900;
            GrassBillboardScreen.DisableKeyword("GRASS_GEOMETRY");
            GrassBillboardScreen.DisableKeyword("GRASS_BLOSSOM");
            GrassBillboardScreen.DisableKeyword("GRASS_BILLBOARD_CROSSED");
            GrassBillboardScreen.EnableKeyword("GRASS_BILLBOARD_SCREEN");
            GrassBillboardScreen.SetTexture("GrassBlades0", BladeTexture2DArray0);
            GrassBillboardScreen.SetInt("EnableHeightTransition", Settings.EnableHeightTransition ? 1 : 0);
            GrassBillboardScreen.SetInt("VertexCount", (int)Settings.GetMinAmountBillboardsPerPatch());
            GrassBillboardScreen.SetFloat("BillboardAlphaCutoff", Settings.BillboardAlphaCutoff);
            GrassBillboardScreen.SetFloat("BillboardHeightAdjustment", Settings.BillboardHeightAdjustment);
            GrassBillboardScreen.SetFloat("BladeHeightCullingThreshold", Settings.BladeHeightCullingThreshold);
            GrassBillboardScreen.SetFloat("LodInstancesBillboardScreen", Settings.LodInstancesBillboardScreen / (float)Settings.LodBillboardScreenTransitionSegments);
            GrassBillboardScreen.SetFloat("LodBillboardScreenTransitionSegments", Settings.LodBillboardScreenTransitionSegments);
            GrassBillboardScreen.SetFloat("LodDistanceBillboardScreenStart", Settings.LodDistanceBillboardScreenStart);
            GrassBillboardScreen.SetFloat("LodDistanceBillboardScreenPeak", Settings.LodDistanceBillboardScreenPeak);
            GrassBillboardScreen.SetFloat("LodDistanceBillboardScreenEnd", Settings.LodDistanceBillboardScreenEnd);

            GrassSimulationComputeShader.SetInt("WindLayerCount", Settings.WindLayerCount);
            GrassSimulationComputeShader.SetFloat("GrassDataResolution", Settings.GrassDataResolution);
            GrassSimulationComputeShader.SetFloat("BladeHeightCullingThreshold", Settings.BladeHeightCullingThreshold);
            GrassSimulationComputeShader.SetFloat("RecoveryFactor", Settings.RecoveryFactor);
            GrassSimulationComputeShader.SetFloat("LodTessellationMin", Settings.LodTessellationMin);
            GrassSimulationComputeShader.SetFloat("LodTessellationMax", Settings.LodTessellationMax);
            GrassSimulationComputeShader.SetFloat("LodDistanceTessellationMin", Settings.LodDistanceTessellationMin);
            GrassSimulationComputeShader.SetFloat("LodDistanceTessellationMax", Settings.LodDistanceTessellationMax);

            //If possible initialize the Data Providers
            // ReSharper disable SuspiciousTypeConversion.Global
            if (DimensionsInput is IInitializableWithCtx)
            {
                ((IInitializableWithCtx)DimensionsInput).Init(this);
            }
            else if (DimensionsInput is IInitializable)
            {
                ((IInitializable)DimensionsInput).Init();
            }

            if (GrassMapInput is IInitializableWithCtx)
            {
                ((IInitializableWithCtx)GrassMapInput).Init(this);
            }
            else if (GrassMapInput is IInitializable)
            {
                ((IInitializable)GrassMapInput).Init();
            }

            if (HeightInput is IInitializableWithCtx)
            {
                ((IInitializableWithCtx)HeightInput).Init(this);
            }
            else if (HeightInput is IInitializable)
            {
                ((IInitializable)HeightInput).Init();
            }

            if (NormalInput is IInitializableWithCtx)
            {
                ((IInitializableWithCtx)NormalInput).Init(this);
            }
            else if (NormalInput is IInitializable)
            {
                ((IInitializable)NormalInput).Init();
            }

            if (PositionInput is IInitializableWithCtx)
            {
                ((IInitializableWithCtx)PositionInput).Init(this);
            }
            else if (PositionInput is IInitializable)
            {
                ((IInitializable)PositionInput).Init();
            }


            GrassInstance = new GrassInstance(this);

            var timePatchConstruction = DateTime.Now;

            PatchContainer.Init(this);
            PatchContainer.SetupContainer();
            Debug.Log("\t Created and initialized " + (Settings.PatchSize * Settings.PatchSize) + " patches and hierarchy in " + (int)(DateTime.Now - timePatchConstruction).TotalMilliseconds + "ms");

            CollisionTextureRenderer = new CollisionTextureRenderer(this, PatchContainer.GetBounds());
            if (WindManager == null)
            {
                WindManager = new WindManager(this);
            }
            else
            {
                WindManager.InitBuffer();
            }
            WindManager.Update();
            //ProceduralWind = new ProceduralWind(this);
            //ProceduralWind.Update();

            var timeBillboardTextures = DateTime.Now;

            //Create Billboard Textures
            BillboardTexturePatchContainer.Init(this);
            BillboardTexturePatchContainer.SetupContainer();
            BillboardTexturePatchContainer.Draw();

            Debug.Log("\t Rendered Billboard Textures in " + (int)(DateTime.Now - timeBillboardTextures).TotalMilliseconds + "ms");

            //Needs to be reset here, since BillboardTexturePatchContainer sets its own NormalHeightTexture
            GrassSimulationComputeShader.SetTexture(KernelPhysics, "NormalHeightTexture", GrassInstance.NormalHeightTexture);
            GrassSimulationComputeShader.SetTexture(KernelSimulationSetup, "NormalHeightTexture", GrassInstance.NormalHeightTexture);

            GrassBillboardCrossed.SetTexture("GrassBillboards", BillboardTexturePatchContainer.BillboardTextures);
            GrassBillboardCrossed.SetTexture("GrassBillboardNormals", BillboardTexturePatchContainer.BillboardNormals);
            GrassBillboardCrossed.SetFloat("BillboardAspect", BillboardTexturePatchContainer.BillboardAspect);
            GrassBillboardCrossed.SetInt("RepetitionCount", (int)PositionInput.GetRepetitionCount());
            GrassBillboardScreen.SetTexture("GrassBillboards", BillboardTexturePatchContainer.BillboardTextures);
            GrassBillboardScreen.SetTexture("GrassBillboardNormals", BillboardTexturePatchContainer.BillboardNormals);
            GrassBillboardScreen.SetFloat("BillboardAspect", BillboardTexturePatchContainer.BillboardAspect);
            GrassBillboardScreen.SetInt("RepetitionCount", (int)PositionInput.GetRepetitionCount());

            Debug.Log("\t Finished Simulation Preperation in " + (int)(DateTime.Now - timeNow).TotalMilliseconds + "ms");

            Settings.LogSettings();

            //Everything is ready.
            IsReady = true;
        }
Пример #6
0
        public static void BatchesFromParticles()
        {
            List <float[]> particlesInfo = new List <float[]>();

            Console.WriteLine("Insert the name of the file to load");
            string filepath = Console.ReadLine();

            float posXmax = float.MinValue;
            float posXmin = float.MaxValue;
            float posYmax = float.MinValue;
            float posYmin = float.MaxValue;
            float posZmax = float.MinValue;
            float posZmin = float.MaxValue;

            BinaryReader reader = new BinaryReader(File.OpenRead(filepath));

            while (reader.BaseStream.Position != reader.BaseStream.Length)
            {
                float posx = reader.ReadSingle();
                float posy = reader.ReadSingle();
                float posz = reader.ReadSingle();
                float dirx = reader.ReadSingle();
                float diry = reader.ReadSingle();

                float[] pInfo = new float[5] {
                    posx, posy, posz, dirx, diry
                };

                //Console.WriteLine("POS: {0},{1},{2} DIR:{3},{4}", posx, posy, posz, dirx, diry);
                particlesInfo.Add(pInfo);

                posXmax = Math.Max(posXmax, posx);
                posXmin = Math.Min(posXmin, posx);
                posYmax = Math.Max(posYmax, posy);
                posYmin = Math.Min(posYmin, posy);
                posZmax = Math.Max(posZmax, posz);
                posZmin = Math.Min(posZmin, posz);
            }
            reader.Close();

            if (particlesInfo == null || !particlesInfo.Any())
            {
                return;
            }
            Random rnd = new Random();

            List <string> archetypes = new List <string>()
            {
                "proc_brittlebush_01", "proc_desert_sage_01", "proc_drygrasses01", "proc_drygrasses01b", "proc_drygrassfronds01", "proc_dryplantsgrass_01", "proc_dryplantsgrass_02", "proc_dry_plants_01", "proc_forest_grass01", "proc_forest_ivy_01", "proc_grassdandelion01", "proc_grasses01", "proc_grasses01b", "proc_grassfronds01", "proc_grassplantmix_01", "proc_grassplantmix_02", "proc_indian_pbrush_01", "proc_leafybush_01", "proc_leafyplant_01", "proc_lizardtail_01", "proc_lupins_01", "proc_meadowmix_01", "proc_meadowpoppy_01", "proc_sage_01", "proc_scrub_bush01", "proc_sml_reeds_01", "proc_sml_reeds_01b", "proc_sml_reeds_01c", "proc_stones_01", "proc_stones_02", "proc_stones_03", "proc_stones_04", "proc_stones_05", "proc_stones_06", "proc_wildquinine", "prop_dandy_b", "prop_dryweed_001_a", "prop_dryweed_002_a", "prop_fernba", "prop_fernbb", "prop_flowerweed_005_a", "prop_grass_001_a", "prop_grass_ca", "prop_grass_da", "prop_log_aa", "prop_log_ab", "prop_log_ac", "prop_log_ad", "prop_log_ae", "prop_log_af", "prop_saplin_001_b", "prop_saplin_001_c", "prop_saplin_002_b", "prop_saplin_002_c", "prop_small_bushyba", "prop_tall_drygrass_aa", "prop_tall_grass_ba", "prop_thindesertfiller_aa", "prop_weed_001_aa", "prop_weed_002_ba", "urbandryfrnds_01", "urbandrygrass_01", "urbangrnfrnds_01", "urbangrngrass_01", "urbanweeds01", "urbanweeds01_l1", "urbanweeds02", "urbanweeds02_l1"
            };
            string archetype = archetypes[rnd.Next(0, archetypes.Count() - 1)];

            Vector3 batchSize = new Vector3(100, 100, 75);
            Vector3 bbmax     = new Vector3(posXmax, posYmax, posZmax);
            Vector3 bbmin     = new Vector3(posXmin, posYmin, posZmin);

            Vector3 numblocks = (bbmax - bbmin) / batchSize;
            //Console.WriteLine("{0},{1},{2}",numblocks.X,numblocks.Y,numblocks.Z);
            int blockX = (int)(numblocks.X + 1);
            int blockY = (int)(numblocks.Y + 1);
            int blockZ = (int)(numblocks.Z + 1);

            Ymap map = new Ymap("instancedData");

            map.CMapData.contentFlags = 1088;
            map.CMapData.physicsDictionaries.Add("v_proc1");

            for (int x = -blockX; x <= blockX; x++)
            {
                for (int y = -blockY; y <= blockY; y++)
                {
                    for (int z = -blockZ; z <= blockZ; z++)
                    {
                        IEnumerable <float[]> currentBatch = Enumerable.Empty <float[]>();

                        float maxX = (x + 1) * batchSize.X;
                        float minX = x * batchSize.X;
                        float maxY = (y + 1) * batchSize.Y;
                        float minY = y * batchSize.Y;
                        float maxZ = (z + 1) * batchSize.Z;
                        float minZ = z * batchSize.Z;

                        ///Console.WriteLine("maxX:{0},minX{1},maxY{2},minY{3},maxZ{4},minZ{5}",maxX,minX,maxY,minY,maxZ,minZ);

                        currentBatch = particlesInfo.Where(a => a[0] < maxX && a[0] >= minX && a[1] < maxY && a[1] >= minY && a[2] < maxZ && a[2] >= minZ).ToList();
                        // Console.WriteLine(currentBatch.Count());

                        if (currentBatch?.Any() ?? false)
                        {
                            BatchAABB     aabb       = new BatchAABB(new Vector4(minX, minY, minZ, 0), new Vector4(maxX, maxY, maxZ, 0));
                            GrassInstance grassBatch = new GrassInstance(archetype);
                            grassBatch.BatchAABB = aabb;

                            foreach (float[] inst in currentBatch)
                            {
                                Vector4 worldPos = new Vector4(inst[0], inst[1], inst[2], 0);
                                Vector4 batchPos = (worldPos - aabb.min) / (aabb.max - aabb.min) * 65535;
                                byte    NormalX  = (byte)((inst[3] + 1) * 0.5 * 255);
                                byte    NormalY  = (byte)((inst[4] + 1) * 0.5 * 255);
                                byte[]  color    = new byte[3] {
                                    150, 150, 150
                                };
                                byte scale = (byte)rnd.Next(0, 255);;

                                Instance i = new Instance(new ushort[] { (ushort)batchPos.X, (ushort)batchPos.Y, (ushort)batchPos.Z }, NormalX, NormalY, color, scale);
                                grassBatch.InstanceList.Add(i);
                            }
                            map.CMapData.instancedData.GrassInstanceList.Add(grassBatch);
                        }
                    }
                }
            }
            map.UpdateExtents(new List <CBaseArchetypeDef>());
            Console.WriteLine("Total batches: {0}", map.CMapData.instancedData.GrassInstanceList.Count);
            Console.WriteLine("Total instances: {0}", particlesInfo.Count);
            map.WriteXML().Save("grass.ymap.xml");
            Console.WriteLine("Exported grass.ymap.xml");
        }