Skip to main content
Add clarifying details to make it easier to understand that changing mesh topology affects the input primitive which gets fed to the shader.
Source Link

I want to point out thatThe input primitive, aka. the selectedmesh fed into the shader, has a MeshTopology setting which can be adjusted in code. The accepted answer suggests usingworks because the default input primitive for a mesh(including imported meshes) is triangle for your input primitive, but/MeshTopology.Triangles.

But if you do thisuse MeshTopology.Triangles, you will be creating more geometry than you need becausefor the shader. Because a single vertex may be part of multiple triangles. You, you will have billboards on top of other billboards. You won't notice it visually, because they overlap perfectly, but it will cost you performance. The fragment shader will be working on duplicate geometry for no reason.

Instead, you should use point/MeshTopology.Points as your input primitive, as your exampleoriginal shader already does, and then tell Unity to draw with points rather than triangles. See

You can use Mesh.SetIndicesMesh.SetIndices to adjust the mesh's topology and then your original shader will work just fine.

Example:

using UnityEngine;

public class UsePointTopologyMeshMode : MonoBehaviour {
    
    [ContextMenu("ConvertToPointTopology")]
    void ConvertToPointTopology() {
        Mesh mesh = GetComponent<MeshFilter>().mesh;
        int[] indices = new int[mesh.vertices.Length];
        for (int i = 0; i < indices.Length; i++) {
            indices[i] = i;
        }
        mesh.SetIndices(indices, MeshTopology.Points, 0);
    }
    
    // Use this for initialization
    void Start () {
        ConvertToPointTopology();
    }
}

I want to point out that the selected answer suggests using triangle for your input primitive, but if you do this, you will be creating more geometry than you need because a single vertex may be part of multiple triangles. You will have billboards on top of billboards. You won't notice it visually, because they overlap perfectly, but it will cost you performance. The fragment shader will be working on duplicate geometry for no reason.

Instead, you should use point as your input primitive, as your example already does, and then tell Unity to draw with points rather than triangles. See Mesh.SetIndices.

Example:

Mesh mesh = GetComponent<MeshFilter>().mesh;
int[] indices = new int[mesh.vertices.Length];
for (int i = 0; i < indices.Length; i++) {
    indices[i] = i;
}
mesh.SetIndices(indices, MeshTopology.Points, 0);

The input primitive, aka. the mesh fed into the shader, has a MeshTopology setting which can be adjusted in code. The accepted answer works because the default input primitive for a mesh(including imported meshes) is triangle/MeshTopology.Triangles.

But if you use MeshTopology.Triangles, you will be creating more geometry than you need for the shader. Because a single vertex may be part of multiple triangles, you will have billboards on top of other billboards. You won't notice it visually, because they overlap perfectly, but it will cost you performance. The fragment shader will be working on duplicate geometry for no reason.

Instead, you should use point/MeshTopology.Points as your input primitive, as your original shader already does, and then tell Unity to draw with points rather than triangles.

You can use Mesh.SetIndices to adjust the mesh's topology and then your original shader will work just fine.

using UnityEngine;

public class UsePointTopologyMeshMode : MonoBehaviour {
    
    [ContextMenu("ConvertToPointTopology")]
    void ConvertToPointTopology() {
        Mesh mesh = GetComponent<MeshFilter>().mesh;
        int[] indices = new int[mesh.vertices.Length];
        for (int i = 0; i < indices.Length; i++) {
            indices[i] = i;
        }
        mesh.SetIndices(indices, MeshTopology.Points, 0);
    }
    
    // Use this for initialization
    void Start () {
        ConvertToPointTopology();
    }
}
Source Link
Croolsby
  • 231
  • 3
  • 8

I want to point out that the selected answer suggests using triangle for your input primitive, but if you do this, you will be creating more geometry than you need because a single vertex may be part of multiple triangles. You will have billboards on top of billboards. You won't notice it visually, because they overlap perfectly, but it will cost you performance. The fragment shader will be working on duplicate geometry for no reason.

Instead, you should use point as your input primitive, as your example already does, and then tell Unity to draw with points rather than triangles. See Mesh.SetIndices.

Example:

Mesh mesh = GetComponent<MeshFilter>().mesh;
int[] indices = new int[mesh.vertices.Length];
for (int i = 0; i < indices.Length; i++) {
    indices[i] = i;
}
mesh.SetIndices(indices, MeshTopology.Points, 0);