private void OnEnable()
    {
        return;

        Debug.Assert(m_compute is null, "The grass compute shader is null", gameObject);
        Debug.Assert(material is null, "The material is null", gameObject);

        DebugHardware();

        if (initialized)
        {
            OnDisable();
        }
        initialized = true;

        var positions = sourceMesh.vertices;
        var tris      = sourceMesh.triangles;

        var vertices = new SourceVertex[positions.Length];

        for (var i = 0; i < vertices.Length; i++)
        {
            vertices[i] = new SourceVertex
            {
                position = positions[i]
            };
        }

        var numSourceTriangles = tris.Length / 3;

        sourceVertBuffer = new ComputeBuffer(vertices.Length, SOURCE_VERT_STRIDE, ComputeBufferType.Structured,
                                             ComputeBufferMode.Immutable);
        sourceVertBuffer.SetData(vertices);
        sourceTriBuffer = new ComputeBuffer(tris.Length, SOURCE_TRI_STRIDE, ComputeBufferType.Structured,
                                            ComputeBufferMode.Immutable);
        sourceTriBuffer.SetData(tris);
        drawBuffer =
            new ComputeBuffer(numSourceTriangles * Mathf.CeilToInt(grassSettings.SettingsData.grassPerVertex * 0.25f),
                              DRAW_STRIDE, ComputeBufferType.Append);
        drawBuffer.SetCounterValue(0);
        argsBuffer      = new ComputeBuffer(1, INDIRECT_ARGS_STRIDE, ComputeBufferType.IndirectArguments);
        m_grassKernelId = m_compute.FindKernel("Main");

        m_compute.SetBuffer(m_grassKernelId, m_sourceVerticesPropertyId, sourceVertBuffer);
        m_compute.SetBuffer(m_grassKernelId, m_sourceTrianglesPropertyId, sourceTriBuffer);
        m_compute.SetBuffer(m_grassKernelId, m_drawTrianglesPropertyId, drawBuffer);
        m_compute.SetBuffer(m_grassKernelId, m_indirectArgsBufferPropertyId, argsBuffer);
        m_compute.SetInt(m_numSourceTrianglesPropertyId, numSourceTriangles);

        material.SetBuffer(m_drawTrianglesPropertyId, drawBuffer);

        m_compute.GetKernelThreadGroupSizes(m_grassKernelId, out var threadGroupSize, out _, out _);
        dispatchSize = Mathf.CeilToInt((float)numSourceTriangles / threadGroupSize);

        localBounds = sourceMesh.bounds;
        localBounds.Expand(1);
    }
        /// <summary>
        /// Indicates whether the current <see cref="DirectedWeightedEdge{TVertex}"/>
        /// is equal to another <see cref="DirectedWeightedEdge{TVertex}"/>.
        /// </summary>
        /// <param name="other">
        /// The <see cref="DirectedWeightedEdge{TVertex}"/> to compare with this
        /// object.
        /// </param>
        /// <returns>
        /// <see langword="true"/> if the other
        /// <see cref="DirectedWeightedEdge{TVertex}"/> is equal to this
        /// <see cref="DirectedWeightedEdge{TVertex}"/>; otherwise,
        /// <see langword="false"/>.
        /// </returns>
        /// <seealso cref="IEquatable{T}.Equals(T)"/>
        public bool Equals(DirectedWeightedEdge <TVertex> other)
        {
            if (other == null)
            {
                return(false);
            }

            return((SourceVertex.Equals(other.SourceVertex) && DestinationVertex.Equals(other.DestinationVertex)) &&
                   Weight.Equals(other.Weight));
        }
예제 #3
0
        /// <inheritdoc />
        public override int GetHashCode()
        {
            var hashCode = 0;

            unchecked
            {
                hashCode ^= SourceVertex.GetHashCode() * 31;
                hashCode ^= TargetVertex.GetHashCode() * 31;
                hashCode ^= Weight.GetHashCode() * 31;
            }
            return(hashCode);
        }
예제 #4
0
        public void ModifyPointAt(int index, Color newColor, Vector2 newUV)
        {
            SourceVertex V = vertices[index];

            vertices[index] = new SourceVertex()
            {
                position = V.position, normal = V.normal, uv = newUV, color = new Vector3(newColor.r, newColor.g, newColor.b)
            };

            DEBUG_uvs[index]    = newUV;
            DEBUG_colors[index] = newColor;

            dirty = true;
            //RebuildDebugMesh();
        }
    private void Initialize()
    {
        Debug.Assert(m_computeShader == null, "Compute Shader Is Missing Or Invalid!", gameObject);
        Debug.Assert(m_material == null, "Flower Material Is Missing Or Invalid!", gameObject);
        Debug.Assert(m_sourceMesh == null, "Source Mesh Is Missing Or Invalid!", gameObject);

        var meshVertPositions = m_sourceMesh.vertices;
        var meshTris          = m_sourceMesh.triangles;

        var meshVertices = new SourceVertex[meshVertPositions.Length];

        for (var i = 0; i < meshVertices.Length; i++)
        {
            meshVertices[i] = new SourceVertex {
                position = meshVertPositions[i]
            };
        }

        var numSourceTriangles = meshTris.Length / 3;

        m_sourceVertBuffer = new ComputeBuffer(meshVertices.Length, SOURCE_VERT_STRIDE, ComputeBufferType.Structured,
                                               ComputeBufferMode.Immutable);
        m_sourceVertBuffer.SetData(meshVertices);

        m_sourceTriBuffer = new ComputeBuffer(meshTris.Length, SOURCE_TRI_STRIDE, ComputeBufferType.Structured,
                                              ComputeBufferMode.Immutable);
        m_sourceTriBuffer.SetData(meshTris);

        m_drawBuffer = new ComputeBuffer(numSourceTriangles, DRAW_STRIDE, ComputeBufferType.Append);

        m_argsBuffer = new ComputeBuffer(1, INDIRECT_ARGS_STRIDE, ComputeBufferType.IndirectArguments);

        m_kernelId = m_computeShader.FindKernel("Main");

        m_computeShader.SetBuffer(m_kernelId, m_sourceVerticesPropertyId, m_sourceVertBuffer);
        m_computeShader.SetBuffer(m_kernelId, m_sourceTrianglesPropertyId, m_sourceTriBuffer);
        m_computeShader.SetBuffer(m_kernelId, m_drawTrianglesPropertyId, m_drawBuffer);
        m_computeShader.SetBuffer(m_kernelId, m_indirectArgsBufferPropertyId, m_argsBuffer);
        m_computeShader.SetInt(m_numSourceTrianglesPropertyId, numSourceTriangles);

        m_material.SetBuffer(m_drawTrianglesPropertyId, m_drawBuffer);

        m_computeShader.GetKernelThreadGroupSizes(m_kernelId, out var threadGroupSize, out _, out _);
        m_dispatchSize = Mathf.CeilToInt((float)numSourceTriangles / threadGroupSize);

        m_localBounds = m_sourceMesh.bounds;
        m_localBounds.Expand(1);
    }
예제 #6
0
        public void AddVertex(Vector3 position)
        {
            SourceVertex newVertex = new SourceVertex(position, Vertices.Count);

            //add edges between vertices if connectable
            foreach (SourceVertex vertex in Vertices)
            {
                if (World.IsValidPath(vertex.Position, position))
                {
                    float distance = vertex.Position.Distance(position);

                    vertex.Edges.AddLast(new Edge(newVertex, distance));
                    newVertex.Edges.AddLast(new Edge(vertex, distance));
                }
            }

            Vertices.AddLast(newVertex);
        }
예제 #7
0
        private static void DecomposeMesh(Mesh mesh, int subMeshIndex, out SourceVertex[] vertices, out int[] indices)
        {
            SubMeshDescriptor subMeshDescriptor = mesh.GetSubMesh(subMeshIndex);

            Vector3[] meshVertices = mesh.vertices;
            Vector2[] meshUVs      = mesh.uv;
            int[]     meshIndices  = mesh.triangles;

            vertices = new SourceVertex[subMeshDescriptor.vertexCount];
            indices  = new int[subMeshDescriptor.indexCount];
            for (int i = 0; i < mesh.vertexCount; ++i)
            {
                int wholeMeshIndex = i + subMeshDescriptor.firstVertex;
                vertices[i] = new SourceVertex {
                    position = meshVertices[wholeMeshIndex], uv = meshUVs[wholeMeshIndex]
                };
            }

            for (int i = 0; i < subMeshDescriptor.indexCount; ++i)
            {
                indices[i] = meshIndices[i + subMeshDescriptor.indexStart] + subMeshDescriptor.baseVertex -
                             subMeshDescriptor.firstVertex;
            }
        }
예제 #8
0
        public Path Search(Vector3 source, Vector3 destination)
        {
            //temporary add source and destination as vertices
            AddVertex(source);
            AddVertex(destination);

            int sourceIndex = Vertices.Count - 2;
            int destIndex = Vertices.Count - 1;
            float[] dist = new float[Vertices.Count];
            SourceVertex[] previous = new SourceVertex[Vertices.Count];
            SourceVertex[] verticesArray = Vertices.ToArray();
            MinHeap heap = new MinHeap(verticesArray.Length);
            LinkedList<Vector3> result = new LinkedList<Vector3>();

            //Dijkstra's algorithm

            //initialize everything to maximum distance
            for (int i = 0; i < dist.Length; i++)
                dist[i] = float.MaxValue;

            //set source distance to 0
            dist[sourceIndex] = 0;

            //add all vertices to heap
            for (int i = 0; i < dist.Length; i++)
                heap.Add(dist[i], i);

            while (heap.Count > 0)
            {
                int u = heap.Poll().Value;

                if (u == destIndex)
                {
                    //destination reached
                    result.AddFirst(verticesArray[u].Position);
                    while (previous[u] != null)
                    {
                        //backtrack to source
                        result.AddFirst(previous[u].Position);
                        u = previous[u].Index;
                    }
                    break;
                }

                //no valid paths
                if (dist[u] == float.MaxValue)
                    break;

                //iterate through all edges
                foreach (Edge edge in verticesArray[u].Edges)
                {
                    int v = edge.Destination.Index;

                    //only check v if v is still in the heap
                    if (!heap.ContainsValue(v))
                        continue;

                    //calculate distance of current path
                    float alt = dist[u] + edge.Distance;
                    if (alt < dist[v])
                    {
                        //current path is shorter
                        dist[v] = alt;
                        previous[v] = verticesArray[u];
                        heap.Update(alt, v);
                    }
                }
            }

            //remove source and destination from vertices list
            RemoveLastVertex();
            RemoveLastVertex();

            if (result.Count == 0)
                return null;

            return new Path(result.ToArray());
        }
예제 #9
0
 public Edge(SourceVertex dest, float dist)
 {
     this.Destination = dest;
     this.Distance = dist;
 }
예제 #10
0
    private void OnEnable()
    {
        // If initialized, call on disable to clean things up
        if (initialized)
        {
            OnDisable();
        }
        initialized = true;

        // Grab data from the source mesh
        Vector3[] positions = sourceMesh.vertices;
        Vector2[] uvs       = sourceMesh.uv;
        int[]     tris      = sourceMesh.triangles;

        // Create the data to upload to the source vert buffer
        SourceVertex[] vertices = new SourceVertex[positions.Length];
        for (int i = 0; i < vertices.Length; i++)
        {
            vertices[i] = new SourceVertex()
            {
                position = positions[i],
                uv       = uvs[i],
            };
        }
        int numTriangles = tris.Length / 3; // The number of triangles in the source mesh is the index array / 3

        // Create compute buffers
        // The stride is the size, in bytes, each object in the buffer takes up
        sourceVertBuffer = new ComputeBuffer(vertices.Length, SOURCE_VERT_STRIDE, ComputeBufferType.Structured, ComputeBufferMode.Immutable);
        sourceVertBuffer.SetData(vertices);
        sourceTriBuffer = new ComputeBuffer(tris.Length, SOURCE_TRI_STRIDE, ComputeBufferType.Structured, ComputeBufferMode.Immutable);
        sourceTriBuffer.SetData(tris);
        // We split each triangle into three new ones
        drawBuffer = new ComputeBuffer(numTriangles * 3, DRAW_STRIDE, ComputeBufferType.Append);
        drawBuffer.SetCounterValue(0); // Set the count to zero
        argsBuffer = new ComputeBuffer(1, ARGS_STRIDE, ComputeBufferType.IndirectArguments);
        // The data in the args buffer corresponds to:
        // 0: vertex count per draw instance. We will only use one instance
        // 1: instance count. One
        // 2: start vertex location if using a Graphics Buffer
        // 3: and start instance location if using a Graphics Buffer
        argsBuffer.SetData(new int[] { 0, 1, 0, 0 });

        // Cache the kernel IDs we will be dispatching
        idPyramidKernel   = pyramidComputeShader.FindKernel("Main");
        idTriToVertKernel = triToVertComputeShader.FindKernel("Main");

        // Set data on the shaders
        pyramidComputeShader.SetBuffer(idPyramidKernel, "_SourceVertices", sourceVertBuffer);
        pyramidComputeShader.SetBuffer(idPyramidKernel, "_SourceTriangles", sourceTriBuffer);
        pyramidComputeShader.SetBuffer(idPyramidKernel, "_DrawTriangles", drawBuffer);
        pyramidComputeShader.SetInt("_NumSourceTriangles", numTriangles);

        triToVertComputeShader.SetBuffer(idTriToVertKernel, "_IndirectArgsBuffer", argsBuffer);

        material.SetBuffer("_DrawTriangles", drawBuffer);

        // Calculate the number of threads to use. Get the thread size from the kernel
        // Then, divide the number of triangles by that size
        pyramidComputeShader.GetKernelThreadGroupSizes(idPyramidKernel, out uint threadGroupSize, out _, out _);
        dispatchSize = Mathf.CeilToInt((float)numTriangles / threadGroupSize);

        // Get the bounds of the source mesh and then expand by the pyramid height
        localBounds = sourceMesh.bounds;
        localBounds.Expand(pyramidHeight);
    }
 /// <summary>
 /// Gets a hash code for this <see cref="DirectedWeightedEdge{TVertex}"/>.
 /// </summary>
 /// <returns>
 /// A hash code for the current <see cref="DirectedWeightedEdge{TVertex}"/>.
 /// </returns>
 public override int GetHashCode()
 {
     return(SourceVertex.GetHashCode()
            ^ DestinationVertex.GetHashCode()
            ^ Weight.GetHashCode());
 }
예제 #12
0
    private void Start()
    {
        // 创建一个较大的 Mesh, 用于存放更多的草地.
        sourceMesh      = gameObject.GetComponent <CreatePlaneMesh>().CreatePlane();
        sourceMesh.name = "Plane Sub";

        Vector3[] positions = sourceMesh.vertices;
        int[]     tris      = sourceMesh.triangles;

        SourceVertex[] vertices = new SourceVertex[positions.Length];
        for (int i = 0; i < vertices.Length; i++)
        {
            vertices[i] = new SourceVertex()
            {
                position = positions[i],
            };
        }
        int numSourceTriangles = tris.Length / 3;

        // 初始化 Buffer.
        sourceVertexBuffer = new ComputeBuffer(vertices.Length, SOURCE_VERT_STRIDE, ComputeBufferType.Structured, ComputeBufferMode.Immutable);
        sourceVertexBuffer.SetData(vertices);

        sourceTriangleBuffer = new ComputeBuffer(tris.Length, SOURCE_TRI_STRIDE, ComputeBufferType.Structured, ComputeBufferMode.Immutable);
        sourceTriangleBuffer.SetData(tris);

        drawTriangleBuffer = new ComputeBuffer(numSourceTriangles * (2 * grassSettings.maxBladeSegments - 1), DRAW_STRIDE, ComputeBufferType.Append);
        drawTriangleBuffer.SetCounterValue(0);

        argsBuffer = new ComputeBuffer(1, INDIRECT_ARGS_STRIDE, ComputeBufferType.IndirectArguments);

        // 设置数据.
        kernelIndex = grassComputeShader.FindKernel("CSMain");

        // 设置 Buffer.
        grassComputeShader.SetBuffer(kernelIndex, "_SourceVertexBuffer", sourceVertexBuffer);
        grassComputeShader.SetBuffer(kernelIndex, "_SourceTriangleBuffer", sourceTriangleBuffer);
        grassComputeShader.SetBuffer(kernelIndex, "_DrawTriangles", drawTriangleBuffer);
        grassComputeShader.SetBuffer(kernelIndex, "_IndirectArgsBuffer", argsBuffer);

        // 设置数量.
        grassComputeShader.SetInt("_NumSourceTriangles", numSourceTriangles);

        // 设置草地数据.
        grassComputeShader.SetFloat("_BladeWidth", grassSettings.bladeWidth);
        grassComputeShader.SetFloat("_BladeWidthRandom", grassSettings.bladeWidthRandom);
        grassComputeShader.SetFloat("_BladeHeight", grassSettings.bladeHeight);
        grassComputeShader.SetFloat("_BladeHeightRandom", grassSettings.bladeHeightRandom);
        grassComputeShader.SetFloat("_BendRotationRandom", grassSettings.bendRotationRandom);
        grassComputeShader.SetFloat("_BladeForward", grassSettings.bladeForward);
        grassComputeShader.SetTexture(kernelIndex, "_WindTexture", grassSettings.windTexture);
        grassComputeShader.SetVector("_WindTextureST", grassSettings.windTextureST);
        grassComputeShader.SetFloat("_WindStrength", grassSettings.windStrength);
        grassComputeShader.SetVector("_WindFrequency", grassSettings.windFrequency);

        grassMaterial.SetBuffer("_DrawTriangles", drawTriangleBuffer);

        // 计算线程分配.
        grassComputeShader.GetKernelThreadGroupSizes(kernelIndex, out uint threadGroupSize, out _, out _);
        dispatchSize = Mathf.CeilToInt((float)numSourceTriangles / threadGroupSize);

        localBounds = sourceMesh.bounds;
        localBounds.Expand(1);
    }
예제 #13
0
 /// <inheritdoc />
 public override string ToString()
 {
     return(string.Format("{0}.{1}[Source={2}, Target={3}, Weight={4}]",
                          GetType().Namespace, GetType().Name, SourceVertex?.ToString(), TargetVertex?.ToString(), Weight?.ToString()));
 }
예제 #14
0
    private void OnEnable()
    {
        // If initialized, call on disable to clean things up
        if (m_Initialized)
        {
            OnDisable();
        }

        // Setup compute shader and material manually

        // Don't do anything if resources are not found,
        // or no vertex is put on the mesh.
        if (grassPainter == null || sourceMesh == null || computeShader == null || material == null)
        {
            return;
        }

        sourceMesh = grassPainter.mesh; // update mesh

        if (sourceMesh.vertexCount == 0)
        {
            return;
        }

        m_Initialized = true;

        // Instantiate the shaders so they can point to their own buffers
        m_InstantiatedComputeShader = Instantiate(computeShader);
        m_InstantiatedMaterial      = Instantiate(material);

        // Grab data from the source mesh
        Vector3[] positions = sourceMesh.vertices;
        Vector3[] normals   = sourceMesh.normals;
        Vector2[] uvs       = sourceMesh.uv;
        Color[]   colors    = sourceMesh.colors;

        // Create the data to upload to the source vert buffer
        SourceVertex[] vertices = new SourceVertex[positions.Length];
        for (int i = 0; i < vertices.Length; i++)
        {
            Color color = colors[i];
            vertices[i] = new SourceVertex()
            {
                position = positions[i],
                normal   = normals[i],
                uv       = uvs[i],
                color    = new Vector3(color.r, color.g, color.b) // Color --> Vector3
            };
        }

        int numSourceVertices = vertices.Length;

        // Each segment has two points
        int maxBladesPerVertex  = Mathf.Max(1, m_AllowedBladesPerVertex);
        int maxSegmentsPerBlade = Mathf.Max(1, m_AllowedSegmentsPerBlade);
        int maxBladeTriangles   = maxBladesPerVertex * ((maxSegmentsPerBlade - 1) * 2 + 1);

        // Create compute buffers
        // The stride is the size, in bytes, each object in the buffer takes up
        m_SourceVertBuffer = new ComputeBuffer(vertices.Length, SOURCE_VERT_STRIDE, ComputeBufferType.Structured, ComputeBufferMode.Immutable);
        m_SourceVertBuffer.SetData(vertices);

        m_DrawBuffer = new ComputeBuffer(numSourceVertices * maxBladeTriangles, DRAW_STRIDE, ComputeBufferType.Append);
        m_DrawBuffer.SetCounterValue(0);

        m_ArgsBuffer = new ComputeBuffer(1, INDIRECT_ARGS_STRIDE, ComputeBufferType.IndirectArguments);

        // Cache the kernel IDs we will be dispatching
        m_IdGrassKernel = m_InstantiatedComputeShader.FindKernel("Main");

        // Set buffer data
        m_InstantiatedComputeShader.SetBuffer(m_IdGrassKernel, "_SourceVertices", m_SourceVertBuffer);
        m_InstantiatedComputeShader.SetBuffer(m_IdGrassKernel, "_GrassTriangles", m_DrawBuffer);
        m_InstantiatedComputeShader.SetBuffer(m_IdGrassKernel, "_IndirectArgsBuffer", m_ArgsBuffer);
        // Set vertex data
        m_InstantiatedComputeShader.SetInt("_NumSourceVertices", numSourceVertices);
        m_InstantiatedComputeShader.SetInt("_MaxBladesPerVertex", maxBladesPerVertex);
        m_InstantiatedComputeShader.SetInt("_MaxSegmentsPerBlade", maxSegmentsPerBlade);

        m_InstantiatedMaterial.SetBuffer("_GrassTriangles", m_DrawBuffer);
        m_InstantiatedMaterial.SetShaderPassEnabled("ShadowCaster", castShadow);

        if (overrideMaterial)
        {
            m_InstantiatedMaterial.SetColor("_TopColor", topColor);
            m_InstantiatedMaterial.SetColor("_BottomColor", bottomColor);
        }

        // Calculate the number of threads to use. Get the thread size from the kernel
        // Then, divide the number of triangles by that size
        m_InstantiatedComputeShader.GetKernelThreadGroupSizes(m_IdGrassKernel, out uint threadGroupSize, out _, out _);
        m_DispatchSize = Mathf.CeilToInt((float)numSourceVertices / threadGroupSize);

        // Get the bounds of the source mesh and then expand by the maximum blade width and height
        m_LocalBounds = sourceMesh.bounds;
        m_LocalBounds.Expand(Mathf.Max(grassHeight + grassRandomHeight, grassWidth));
    }