Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Line thickness

Discussion in 'Shaders' started by oLDo, Nov 12, 2018.

  1. oLDo

    oLDo

    Joined:
    Mar 14, 2017
    Posts:
    55
    Hi.
    I have solution to do something and the result is a mesh with topology lines. But I need to change the thickness of those lines. I can't use line renderer. I'm trying to write shader to achieve this. I'm not very good in shader, I need some help. If it will be stupid, like in screenpos it will move each vertex in x/y by some input, it doesn't matter for me.

    I have this, but isn't moving that vertex by pixels, by unity units.
    Code (CSharp):
    1. Shader "Volke/Mesh lines" {
    2.     Properties{
    3.         _Color("Color", Color) = (1, 1, 1, 1)
    4.         _Thickness("Thickness", float) = 1
    5.     }
    6.         SubShader{
    7.             Tags {
    8.                 "RenderType" = "Opaque"
    9.                 "Queue" = "Geometry+3000"
    10.             }
    11.             Blend SrcAlpha One
    12.  
    13.             Pass {
    14.                 CGPROGRAM
    15.  
    16.                 #pragma vertex vert
    17.                 #pragma fragment frag
    18.                 #include "UnityCG.cginc"
    19.  
    20.                 struct v2f {
    21.                     float4 pos : SV_POSITION;
    22.                 };
    23.  
    24.                 fixed4 _Color;
    25.                 float _Thickness;
    26.  
    27.                 v2f vert(appdata_base v)
    28.                 {
    29.                     v2f o;
    30.                     o.pos = UnityObjectToClipPos(v.vertex);
    31.                     return o;
    32.                 }
    33.  
    34.                 fixed4 frag(v2f i) : SV_Target
    35.                 {
    36.                     return _Color;
    37.                 }
    38.                 ENDCG
    39.             }
    40.            
    41.             Pass {
    42.                 CGPROGRAM
    43.  
    44.                 #pragma vertex vert
    45.                 #pragma fragment frag
    46.                 #include "UnityCG.cginc"
    47.  
    48.                 struct v2f {
    49.                     float4 pos : SV_POSITION;
    50.                 };
    51.  
    52.                 fixed4 _Color;
    53.                 float _Thickness;
    54.  
    55.                 v2f vert(appdata_base v)
    56.                 {
    57.                     v2f o;
    58.                     o.pos = UnityObjectToClipPos(v.vertex);
    59.                     o.pos.x += _Thickness;
    60.                     return o;
    61.                 }
    62.  
    63.                 fixed4 frag(v2f i) : SV_Target
    64.                 {
    65.                     return _Color;
    66.                 }
    67.                 ENDCG
    68.             }
    69.  
    70.  
    71.     }
    72.         FallBack Off
    73. }
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    If I understand correctly, you have a mesh that is itself just the topological lines you want to draw, yes? Like lots of thin strips of geometry? And you want to make those lines thicker dynamically?

    The short answer is you can't. Not without doing a lot more work to the mesh itself to store the data you need. To move the vertices such that the line gets thicker means needing to move the vertices away from the center of the line. Vertex shaders don't know anything about other vertices or the triangle(s) it is apart of, so you have to store that information in the vertices themselves, usually in the extra UV channels. This is usually in the form of some kind of per vertex "center point" or direction that you can use to determine which way to push the vertices.

    However depending on exactly what kind of topology you need, you're probably better off using a different technique all together, something like this asset:
    https://assetstore.unity.com/packag...ame-shader-the-amazing-wireframe-shader-18794
     
  3. oLDo

    oLDo

    Joined:
    Mar 14, 2017
    Posts:
    55
    No dynamically. Just set one size for all. Because default is just 1px.

    I don't have mesh to get a wireframe from it. I have mathematically computed cutting plane through a lot of meshes. The result is interesection points which is source for my lines.
     
  4. oLDo

    oLDo

    Joined:
    Mar 14, 2017
    Posts:
    55
    If I achieve vertex displacement in shader, only one pixel for each direction (on screen), it will be enough. I don't need to set thickness by value, I need them just little more thicker.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    So, you’re generating a runtime mesh that’s using MeshTopology.Lines or LineStrip and you want it to render with a width wider than 1 pixel?

    It seems like right now you’re trying to draw the line a second time offset by 1 pixel to thicken it. That’s possible, but it probably won’t work as well as you think. There’s a good chance it’ll show as two lines rather than one thicker line as the two lines may leave a few pixels open between them.

    However if you want to try that route, o.pos is in clip space. In clip space, x and y are in -w to w ranges for what’s visible on screen, so to move something by 1 pixel to the right you’d need to do this:

    o.pos.x += o.pos.w / _ScreenParams.x * 0.5;

    _ScreenParams is a built in float4 value where the x & y values are the current screen resolution. You can move the line up 1 pixel using .y instead of .x in the two uses of it.

    However the usual recommended way to do what you’re trying to do is to use a geometry shader to expand the line topology into a mesh strip, or to use the built in line renderer, or the Vectrosity asset on the store.
     
  6. oLDo

    oLDo

    Joined:
    Mar 14, 2017
    Posts:
    55
    Yes, exactly.

    Thanks for explanation how to move something by one pixel. It's what I need. I just make 4 passes to move by 1px to all directions and I get thicker line :)

    Code (CSharp):
    1. Shader "Volke/Mesh lines" {
    2.     Properties{
    3.         _Color("Color", Color) = (1, 1, 1, 1)
    4.     }
    5.         SubShader{
    6.             Tags {
    7.                 "RenderType" = "Opaque"
    8.                 "Queue" = "Geometry+3000"
    9.             }
    10.  
    11.             Pass {
    12.                 CGPROGRAM
    13.  
    14.                 #pragma vertex vert
    15.                 #pragma fragment frag
    16.                 #include "UnityCG.cginc"
    17.  
    18.                 struct v2f {
    19.                     float4 pos : SV_POSITION;
    20.                 };
    21.  
    22.                 fixed4 _Color;
    23.  
    24.                 v2f vert(appdata_base v)
    25.                 {
    26.                     v2f o;
    27.                     o.pos = UnityObjectToClipPos(v.vertex);
    28.                     return o;
    29.                 }
    30.  
    31.                 fixed4 frag(v2f i) : SV_Target
    32.                 {
    33.                     return _Color;
    34.                 }
    35.                 ENDCG
    36.             }
    37.            
    38.             Pass {
    39.                 CGPROGRAM
    40.  
    41.                 #pragma vertex vert
    42.                 #pragma fragment frag
    43.                 #include "UnityCG.cginc"
    44.  
    45.                 struct v2f {
    46.                     float4 pos : SV_POSITION;
    47.                 };
    48.  
    49.                 fixed4 _Color;
    50.  
    51.                 v2f vert(appdata_base v)
    52.                 {
    53.                     v2f o;
    54.                     o.pos = UnityObjectToClipPos(v.vertex);
    55.                     o.pos.x += o.pos.w / _ScreenParams.x * 0.5;
    56.                     return o;
    57.                 }
    58.  
    59.                 fixed4 frag(v2f i) : SV_Target
    60.                 {
    61.                     return _Color;
    62.                 }
    63.                 ENDCG
    64.             }
    65.  
    66.             Pass {
    67.                 CGPROGRAM
    68.  
    69.                 #pragma vertex vert
    70.                 #pragma fragment frag
    71.                 #include "UnityCG.cginc"
    72.  
    73.                 struct v2f {
    74.                     float4 pos : SV_POSITION;
    75.                 };
    76.  
    77.                 fixed4 _Color;
    78.  
    79.                 v2f vert(appdata_base v)
    80.                 {
    81.                     v2f o;
    82.                     o.pos = UnityObjectToClipPos(v.vertex);
    83.                     o.pos.x -= o.pos.w / _ScreenParams.x * 0.5;
    84.                     return o;
    85.                 }
    86.  
    87.                 fixed4 frag(v2f i) : SV_Target
    88.                 {
    89.                     return _Color;
    90.                 }
    91.                 ENDCG
    92.             }
    93.  
    94.             Pass {
    95.                 CGPROGRAM
    96.  
    97.                 #pragma vertex vert
    98.                 #pragma fragment frag
    99.                 #include "UnityCG.cginc"
    100.  
    101.                 struct v2f {
    102.                     float4 pos : SV_POSITION;
    103.                 };
    104.  
    105.                 fixed4 _Color;
    106.  
    107.                 v2f vert(appdata_base v)
    108.                 {
    109.                     v2f o;
    110.                     o.pos = UnityObjectToClipPos(v.vertex);
    111.                     o.pos.y += o.pos.w / _ScreenParams.y * 0.5;
    112.                     return o;
    113.                 }
    114.  
    115.                 fixed4 frag(v2f i) : SV_Target
    116.                 {
    117.                     return _Color;
    118.                 }
    119.                 ENDCG
    120.             }
    121.  
    122.             Pass{
    123.                 CGPROGRAM
    124.  
    125.                 #pragma vertex vert
    126.                 #pragma fragment frag
    127.                 #include "UnityCG.cginc"
    128.  
    129.                 struct v2f {
    130.                     float4 pos : SV_POSITION;
    131.                 };
    132.  
    133.                 fixed4 _Color;
    134.  
    135.                 v2f vert(appdata_base v)
    136.                 {
    137.                     v2f o;
    138.                     o.pos = UnityObjectToClipPos(v.vertex);
    139.                     o.pos.y -= o.pos.w / _ScreenParams.y * 0.5;
    140.                     return o;
    141.                 }
    142.  
    143.                 fixed4 frag(v2f i) : SV_Target
    144.                 {
    145.                     return _Color;
    146.                 }
    147.                 ENDCG
    148.             }
    149.  
    150.     }
    151.         FallBack Off
    152. }
     
    Circool and dev-waqas like this.
  7. sebastianwouters

    sebastianwouters

    Joined:
    Nov 9, 2021
    Posts:
    4
  8. mabulous

    mabulous

    Joined:
    Jan 4, 2013
    Posts:
    198
    glLineWidth is a remnant of older graphics generations. Implementations are only required to support a line width of 1, and often will support only that. Those who do support linesidths greater than 1 will internally just convert them to quads and render those. That's probably why it's not exposed in unity.
    Most portable way is to either prepare the mesh with quads and shift vertices around in the vertex shader, or use a geometry shader to create the quad geometry from line primitives.