Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

DX11 PSIZE Bug, PLEASE HELP!

Discussion in 'Shaders' started by ABC295, Feb 1, 2016.

  1. ABC295

    ABC295

    Joined:
    Mar 5, 2013
    Posts:
    8
    I think I have found a bug in DX11 in Unity and would like to hear your advice on if this is a bug and how to get around it.

    What I have working so far is a point cloud renderer that estimates the size of each point depending on it's distance to the camera. Therefore, those points that are close to the camera are rendered larger as they are closer, and those poihnts that are further away are rendered smaller. This works perfectly in DX9 and also in OpenGL (v2 & v4). As I move around the PSIZE value of each vertex is set and DX/GL uses this value to draw each point.

    However, when I use DX11 it ignores the PSIZE value of a vertex, and all points are rendered with the size of 1 (very small). Typically, and quite disastrously, another component of the project needs DX11, so I need to use DX11.

    Can you suggest a work around where each point will be rendered according to it's PSIZE in DX11? I need it to run FAST so I can renderer all of the content, thanks in advance for any help


    Mesh Renderer Setup Code:
    Code (CSharp):
    1. mesh.vertices = points;
    2. mesh.colors = colours;
    3. mesh.SetIndices(indicies, MeshTopology.Points, 0);
    4. mesh.uv = new Vector2[pointCount];
    5. mesh.normals = new Vector3[pointCount];
    6.  
    Shader Code:
    Code (csharp):
    1. Shader "Custom/PointCloudEx"
    2. {
    3.     Properties
    4.     {
    5.         _PointSize("Point Size", Float) = 10.0
    6.     }
    7.  
    8.     SubShader
    9.     {
    10.         Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    11.  
    12.         Pass
    13.         {
    14.             cull Off ZWrite On Blend SrcAlpha OneMinusSrcAlpha
    15.  
    16.             LOD 200
    17.  
    18.             CGPROGRAM
    19.             #pragma exclude_renderers flash
    20.  
    21.             //tells the rederer which function to use to process the rentering of each point (vertex) in the mesh
    22.             #pragma vertex vert                
    23.  
    24.             //tells the renderer which function to use to process the renderering of each pixel (fragment) in the scene
    25.             #pragma fragment frag            
    26.  
    27.             #include "UnityCG.cginc"
    28.  
    29.             float _PointSize;
    30.  
    31.             struct VertexInput
    32.             {
    33.                 float4 v : POSITION;
    34.                 float4 color: COLOR;
    35.             };
    36.  
    37.             struct VertexOutput
    38.             {
    39.                 float4 pos : SV_POSITION;
    40.                 float4 col : COLOR;
    41.                 float size : PSIZE;
    42.             };
    43.  
    44.             VertexOutput vert(VertexInput v)
    45.             {
    46.                 VertexOutput o;
    47.                 o.pos = mul(UNITY_MATRIX_MVP, v.v);
    48.                 o.col = v.color;
    49.                 //Set the point size to be relative to the vertex's distance from the camera
    50.                 o.size = (1.0/ length(WorldSpaceViewDir(v.v))) * _PointSize;
    51.  
    52.                 return o;
    53.             }
    54.  
    55.             float4 frag(VertexOutput o) : COLOR
    56.             {
    57.                 return o.col;
    58.             }
    59.  
    60.             ENDCG
    61.         }
    62.     }
    63. }
    64.  
     
    Last edited: Feb 1, 2016
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    DX11 doesn't support point mode rendering anymore according to the documentation, so I'm surprised it works at all. The idea behind that is that it is replaced by geometry shaders. So you'll have to generate a quad at every vertex yourself using a geometry shader.
     
  3. ABC295

    ABC295

    Joined:
    Mar 5, 2013
    Posts:
    8
    Thanks for the response jvo3dc. Ignoring my misgivings of DX dropping this really fast and useful function (boo Microsoft) can you give more detail as to a work around? I've gone and looked into a Geometry shader myself and my latest working prototype is below.

    However, when I use this shader it makes Unity 5.3 go REALLY slow (2fps on my machine) and when I stop the running scenario Unity crashes (but is solid till I press stop).

    I seem to have found the issue, if I remove the line labelled "TROUBLE LINE" then it goes really fast and doesn't crash, but I need that line to scale the points. Help?


    Code (CSharp):
    1. Shader "Custom/PointCloudEx2"
    2. {
    3.     Properties
    4.     {
    5.         _PointSize("Point Size", Range(0.001, 1)) = 0.005
    6.     }
    7.  
    8.         SubShader
    9.     {
    10.         Pass
    11.     {
    12.         Tags{ "RenderType" = "Opaque" }
    13.         LOD 200
    14.  
    15.         CGPROGRAM
    16.  
    17. #pragma vertex VERT
    18. #pragma fragment FRAG
    19. #pragma geometry GEO
    20.  
    21. #include "UnityCG.cginc"
    22.  
    23.     struct VERT_INPUT
    24.     {
    25.         float4 pos : POSITION;
    26.         float4 color : COLOR;
    27.     };
    28.  
    29.     struct GEO_INPUT
    30.     {
    31.         float4    pos    : POSITION;
    32.         fixed4 color : COLOR;
    33.     };
    34.  
    35.     struct FRAG_INPUT
    36.     {
    37.         float4    pos    : POSITION;
    38.         fixed4 color : COLOR;
    39.     };
    40.  
    41.     float _PointSize;
    42.  
    43.     GEO_INPUT VERT(VERT_INPUT v)
    44.     {
    45.         GEO_INPUT o = (GEO_INPUT)0;
    46.         o.pos = v.pos;
    47.         o.color = v.color;
    48.         return o;
    49.     }
    50.  
    51.     [maxvertexcount(4)]
    52.     void GEO(point GEO_INPUT p[1], inout TriangleStream<FRAG_INPUT> triStream)
    53.     {
    54.         float3 cameraUp = UNITY_MATRIX_IT_MV[1].xyz;
    55.         float3 cameraForward = normalize(UNITY_MATRIX_IT_MV[2].xyz);
    56.         float3 right = cross(cameraUp, cameraForward);
    57.  
    58.         float4 v[4];
    59. /*TROUBLE LINE*/
    60.         float size = (1.0 / length(WorldSpaceViewDir(v.pos))) * _PointSize;
    61.         v[0] = float4(p[0].pos + size * right - size * cameraUp, 1.0f);
    62.         v[1] = float4(p[0].pos + size * right + size * cameraUp, 1.0f);
    63.         v[2] = float4(p[0].pos - size * right - size * cameraUp, 1.0f);
    64.         v[3] = float4(p[0].pos - size * right + size * cameraUp, 1.0f);
    65.  
    66.         float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
    67.  
    68.         FRAG_INPUT newVert;
    69.  
    70.         newVert.pos = mul(vp, v[0]);
    71.         newVert.color = p[0].color;
    72.         triStream.Append(newVert);
    73.  
    74.         newVert.pos = mul(vp, v[1]);
    75.         newVert.color = p[0].color;
    76.         triStream.Append(newVert);
    77.  
    78.         newVert.pos = mul(vp, v[2]);
    79.         newVert.color = p[0].color;
    80.         triStream.Append(newVert);
    81.  
    82.         newVert.pos = mul(vp, v[3]);
    83.         newVert.color = p[0].color;
    84.         triStream.Append(newVert);
    85.     }
    86.  
    87.     fixed4 FRAG(FRAG_INPUT input) : COLOR
    88.     {
    89.         return input.color;
    90.     }
    91.  
    92.         ENDCG
    93.     }
    94.     }
    95. }
    96.  
     
  4. ABC295

    ABC295

    Joined:
    Mar 5, 2013
    Posts:
    8
    Also found lots of references in the DX11 documentation to point rendering so I wouldn't say they've dropped it altogether. One of Microsoft's DX11 render modes in D3D11_PRIMITIVE_TOPOLOGY is POINTLIST.
     
  5. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Yes, it is a bit confusing. A similar talk is going on here. So, lets say that as far as I've heard, they dropped point mode rendering. But that does not seem 100% true. It seems they just dropped point sprites, which is probably exactly why PSIZE doesn't work anymore.

    When it comes to your shader, you should probably try to just generate the quads in the geometry shader. Then pass along the size to the vertex shader and move the vertices to the right position there.
     
  6. ABC295

    ABC295

    Joined:
    Mar 5, 2013
    Posts:
    8
    Ye I had that exact same thought, but same effect. Can you replicate it your end?
     
  7. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I haven't tried to replicate it, but 2 fps does sound really slow. You could also try to not use WorldSpaceViewDir. Just directly take the distance between the world space position of the vertex and the camera. So something like:
    Code (csharp):
    1.  
    2. float3 pos_world = mul(UNITY_MATRIX_MVP, v.pos).xyz;
    3. float size = _PointSize / distance(pos_world, _WorldSpaceCameraPos);
    4.  
    Though this should not make that much of a difference really.