Search Unity

Help me modify Wireframe shader.

Discussion in 'Shaders' started by Frenzy07, Jun 22, 2014.

  1. Frenzy07

    Frenzy07

    Joined:
    Nov 21, 2012
    Posts:
    12
    I want lines to be displayed only on the contours of polygons.
    Pictured above from left as the current shader look. At right what i need. I understand that it is necessary to have data on the edges of polygons.


    Code (CSharp):
    1.  
    2. Shader "Custom/Wireframe"
    3. {
    4.     Properties
    5.     {
    6.         _WireColor("WireColor", Color) = (1,0,0,1)
    7.         _Color("Color", Color) = (1,1,1,1)
    8.     }
    9.     SubShader
    10.     {
    11.  
    12.         Pass
    13.         {
    14.             CGPROGRAM
    15.             #include "UnityCG.cginc"
    16.             #pragma target 5.0
    17.             #pragma vertex vert
    18.             #pragma geometry geom
    19.             #pragma fragment frag
    20.          
    21.             half4 _WireColor, _Color;
    22.      
    23.             struct v2g
    24.             {
    25.                 float4  pos : SV_POSITION;
    26.                 float2  uv : TEXCOORD0;
    27.             };
    28.          
    29.             struct g2f
    30.             {
    31.                 float4  pos : SV_POSITION;
    32.                 float2  uv : TEXCOORD0;
    33.                 float3 dist : TEXCOORD1;
    34.             };
    35.  
    36.             v2g vert(appdata_base v)
    37.             {
    38.                 v2g OUT;
    39.                 OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    40.                 OUT.uv = v.texcoord; //the uv's arent used in this shader but are included in case you want to use them
    41.                 return OUT;
    42.             }
    43.          
    44.             [maxvertexcount(3)]
    45.             void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream)
    46.             {
    47.          
    48.                 float2 WIN_SCALE = float2(_ScreenParams.x/2.0, _ScreenParams.y/2.0);
    49.              
    50.                 //frag position
    51.                 float2 p0 = WIN_SCALE * IN[0].pos.xy / IN[0].pos.w;
    52.                 float2 p1 = WIN_SCALE * IN[1].pos.xy / IN[1].pos.w;
    53.                 float2 p2 = WIN_SCALE * IN[2].pos.xy / IN[2].pos.w;
    54.              
    55.                 //barycentric position
    56.                 float2 v0 = p2-p1;
    57.                 float2 v1 = p2-p0;
    58.                 float2 v2 = p1-p0;
    59.                 //triangles area
    60.                 float area = abs(v1.x*v2.y - v1.y * v2.x);
    61.          
    62.                 g2f OUT;
    63.                 OUT.pos = IN[0].pos;
    64.                 OUT.uv = IN[0].uv;
    65.                 OUT.dist = float3(area/length(v0),0,0);
    66.                 triStream.Append(OUT);
    67.  
    68.                 OUT.pos = IN[1].pos;
    69.                 OUT.uv = IN[1].uv;
    70.                 OUT.dist = float3(0,area/length(v1),0);
    71.                 triStream.Append(OUT);
    72.  
    73.                 OUT.pos = IN[2].pos;
    74.                 OUT.uv = IN[2].uv;
    75.                 OUT.dist = float3(0,0,area/length(v2));
    76.                 triStream.Append(OUT);
    77.              
    78.             }
    79.          
    80.             half4 frag(g2f IN) : COLOR
    81.             {
    82.                 //distance of frag from triangles center
    83.                 float d = min(IN.dist.x, min(IN.dist.y, IN.dist.z));
    84.                 //fade based on dist from center
    85.                  float I = exp2(-4.0*d*d);
    86.                
    87.                  return lerp(_Color, _WireColor, I);              
    88.             }
    89.          
    90.             ENDCG
    91.  
    92.         }
    93.     }
    94. }
     

    Attached Files:

  2. frogsbo

    frogsbo

    Joined:
    Jan 16, 2014
    Posts:
    79
    That's difficult because you are only selecting the polygons that have a right angle, any edges that are not on the same plane. the code is written with trianges and you would kindof want to do square area outlines. for the moment, you can see if you can just select lines that are at right angles, i.e. only draw edges where the two points share two of their x, y or z coordnates
     
  3. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Doing this in a shader is only possible with shader model 4+. (So also DirectX 10+.)

    Another way is to change the model and make it consist of (infinitely thin) tubes running over the edges you want to render. This will of course make the model heavier and more complex.

    Edit: I see you are already using shader model 4+. One way would be to compare the normals of the neighbouring triangles. If the dot product of the two normals is (close to) 1, the edge can be skipped.
     
  4. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
    • Meshes: Added "keep quads" mesh import option; useful for DX11/Console tessellation shaders.
    Coming soon - Unity 5 closed beta.
     
  5. sschaem

    sschaem

    Joined:
    Feb 14, 2014
    Posts:
    148
    jvo3dc: I also believe using face normal is the way to go for a general co planar solution, and bonus you can correct AA for outline wireframe edge.
    But this require adjacency support in the geometry shader, and I dont believe Unity exposes this ? (doesnt work for me)

    I have a simple overlay wireframe shader that I use in game mode to show triangle or quad (using SV_VertexID instead of a geo shader), but it assume the vertices are ordered in a predictable sequence. (Add material slot, set shader, done.)

    Sadly, you can make a more generic Dx9 class wireframe shader by simply passing a stream that include the vertex index ("Primitive point ID") to the shader.
    This vertex index as been in HW since the first vertex shader implementation (required for the GPU to index memory), so not sure why HW vendor are still keeping this away from developers, but yet they did expose SV_VertexID in Dx10 (that is the vertex stream index, but only when its not parsing indexed primitive)... go figure.

    wire.png