Search Unity

Geometry shader with MeshTopology.LineStrip ?

Discussion in 'Shaders' started by Avol, May 26, 2019.

  1. Avol

    Avol

    Joined:
    May 27, 2016
    Posts:
    95
    Is it possible to use something like a geometry shader to draw multiple lines from a single line strip mesh? Geometry shader works with triangles and MeshTopology.LineStrip does not have tris.
    Thinking of a way to save memory when drawing hundreds of lines with small noise factor along 1 line.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Geomerty shaders have an input and output type, and they don't have to match. If your mesh is using a line topology, then use the line input type.

    However Unity doesn't have adjacency support, so you'd have to store the next vertex position in the vertex data. You might be better off using triangle topology still, with each triangle being the two points of the line plus the next vertex.
     
    andrew-lukasik and Avol like this.
  3. Avol

    Avol

    Joined:
    May 27, 2016
    Posts:
    95
    I came to such a solution:

    Code (CSharp):
    1.  
    2.              void ComputeQuadPoints(float4 p1, float4 p2,
    3.                                     out float4 o1, out float4 o2, out float4 o3, out float4 o4)
    4.              {
    5.                 float2 dir      = normalize(p2.xy - p1.xy);
    6.                 float2 normal   = float2(-dir.y, dir.x);
    7.                 float4 offset1  = float4(normal * 0.05f / 2.0f, 0, 0);
    8.                 float4 offset2  = float4(normal * 0.05f / 2.0f, 0, 0);
    9.                 o1 = p1 + offset1;
    10.                 o2 = p1 - offset1;
    11.  
    12.                 o3 = p2 + offset2;
    13.                 o4 = p2 - offset2;
    14.              }
    15.            
    16.              [maxvertexcount(100)]
    17.              void geom(line input p[2], inout TriangleStream<input> triStream)
    18.              {
    19.                 input g[4];
    20.                 uint id = p[0].pos.w;
    21.  
    22.                 // get line quad
    23.                 float4 p1 = UnityObjectToClipPos(float4(p[0].pos.xyz, 1));
    24.                 float4 p2 = UnityObjectToClipPos(float4(p[1].pos.xyz, 1));
    25.                 float4 o1, o2, o3, o4 = 0;
    26.                 ComputeQuadPoints(p1, p2, o1, o2, o3, o4);
    27.                 // get prev line quad
    28.                 bool prevExists = false;
    29.                 float4 oP1 = 0; float4 oP2 = 0; float4 oP3 = 0; float4 oP4 = 0;
    30.                 if (id > 0)
    31.                 {
    32.                     float4 p1 = UnityObjectToClipPos(float4(_Points[id - 2].pos0.xyz, 1));
    33.                     float4 p2 = UnityObjectToClipPos(float4(_Points[id - 1].pos0.xyz, 1));
    34.                     ComputeQuadPoints(p1, p2, oP1, oP2, oP3, oP4);
    35.                     prevExists = true;
    36.                 }
    37.  
    38.                 // draw strands
    39.                 for (int x = 0; x < 5; x++)
    40.                 {
    41.                     for (int y = 0; y < 5; y++)
    42.                     {
    43.                         float   rndX    = nrand(float2(x, y));
    44.                         float   rndY    = nrand(float2(y, -x));
    45.                         float4  noise   = float4(rndX, rndY, 0, 0);
    46.  
    47.                         if (!prevExists)
    48.                         {
    49.                             g[0].pos    = o1 + noise;
    50.                             g[1].pos    = o2 + noise;
    51.                         }
    52.                         else
    53.                         {
    54.                             g[0].pos    = oP3 + noise;
    55.                             g[1].pos    = oP4 + noise;
    56.                         }
    57.          
    58.  
    59.                         g[2].pos    = o3 + noise;
    60.                         g[3].pos    = o4 + noise;
    61.                        
    62.                         triStream.Append(g[0]);
    63.                         triStream.Append(g[1]);
    64.                         triStream.Append(g[2]);
    65.                         triStream.Append(g[3]);
    66.                     }
    67.                 }
    68.             }
     
  4. Hyp-X

    Hyp-X

    Joined:
    Jun 24, 2015
    Posts:
    438
    Does your solution works with DirectX12 ?
    I have a similar shader that works with DirectX11 but not with 12
    I get:
    d3d12: the given primitive topology does not match the topology expected by the geometry shader.
    but I suspect it's a Unity bug (2019.2.7f2)
     
  5. Avol

    Avol

    Joined:
    May 27, 2016
    Posts:
    95
    Yes, though I tweaked it quite a bit since this post. Are you using MeshTopology.Lines instead of MeshTopology.LineStrip?