Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Feedback Wanted: Mesh scripting API improvements

Discussion in 'Graphics Experimental Previews' started by Aras, May 26, 2019.

  1. KillHour

    KillHour

    Joined:
    Oct 25, 2015
    Posts:
    22
    I'm working on a custom fork of the current HDRP package that will let me do this. I'll report back when (if) I get it working...
     
    Mr-Mechanical likes this.
  2. KillHour

    KillHour

    Joined:
    Oct 25, 2015
    Posts:
    22
    The good news - I was able to modify the HDRP shaders to optionally take a compute buffer for vertex data without breaking anything else (as far as I could tell).

    The bad news - shader graph is totally independent of that and has some crazy C# shader string builder that I'll need to figure out.
     
    BanJaxe and Mr-Mechanical like this.
  3. caioc2bolado

    caioc2bolado

    Joined:
    May 11, 2018
    Posts:
    2
    I've been testing with the new mesh slice set/get and the results are not good. (2019.3.0a5)

    My case is very simple: every frame a generate the "skeleton" of the mesh(variable number of vertices) and expand it in the geometry shader.

    Using the the Mesh class it takes ~16ms per frame to setup the data. Skipping the entire mesh class and passing the same data through compute buffers and using DrawProcedural takes ~0.7ms per frame.

    I have no idea how much copying/reallocating and checking there is inside the mesh class, but in its current form it is far away from the performance it should be.

    Looking forward for the SetIndexBufferData & SetVertexBufferData.
     
  4. Dingoblue

    Dingoblue

    Joined:
    Aug 23, 2018
    Posts:
    2
    Is there no version of SetTriangles that takes a NativeArray of ushort or int?
    Using:
    filter.sharedMesh.SetIndices(Triangles, MeshTopology.Triangles, 0);


    To work around this for now, but it seems like an oversight.
     
    Lynxed likes this.
  5. KillHour

    KillHour

    Joined:
    Oct 25, 2015
    Posts:
    22
    I modified the Shadergraph package to inject my custom vertex code into the generated shaders (right now, it's just a hardcoded triangle for testing). It works in the preview windows, but the main preview doesn't reflect it, and neither does using the shader in a scene. Does the master node get its vertex information from somewhere else? What is going on here? shadergraphh.PNG

    Edit:

    Oh crap, I know EXACTLY what's going on here. That "position" input is just completely replacing anything I do with vertex shaders. I'm a dummy.

    Double Edit:

    It should be possible to do all of this with just a custom function node if I could get
    SV_VertexID into it. I don't think that's possible right now, but I'm going to keep digging through the code. Might be a fairly easy request for the shadergraph team.
     
    Last edited: Jul 19, 2019
  6. KillHour

    KillHour

    Joined:
    Oct 25, 2015
    Posts:
    22
    I figured it out - Shader Graph does use the HDRP shaders, but ONLY for the actual output, not the preview nodes. I didn't actually have to modify the Shader Graph package at all. I just had to turn on the define I used to turn the procedural vertex piece on. I created a dummy custom function that didn't do anything except sneak a #define in there.

    Code (csharp):
    1. #define PROCEDURAL_MESH_ON
    2. Out = In;
    blob.PNG

    That's an unlit base shader - I'm using shader graph to lower the brightness based on the normal angle from the camera.
     
    Last edited: Jul 19, 2019
  7. alexnown

    alexnown

    Joined:
    Oct 25, 2018
    Posts:
    20
    This api is very useful for me. In my game I'm serialize flat mesh data (Vector2 [] vertices and ushort [] triangles) to BlobAsset, then at runtime casts BlobReference<T> -> NativeArray<T> and sets it to mesh. Is it already possible set vertices dimension to 2? Now I'm always get error:
    Code (CSharp):
    1. ArgumentException: SetVertices with NativeArray should use struct type that is 12 bytes (3x float) in size
    Will it be possible in future? It will be wrong serialize flat mesh vertices as Vector3 with always z=0.
     
  8. Lynxed

    Lynxed

    Joined:
    Dec 9, 2012
    Posts:
    55
    As soon as we get SetFoo, can we please have GetFoo(NativeArray<T>)? including GetTriangles(NativeArray<int>) and GetColors(NativeArray<float4>) pretty please?
    Having SetTriangles(NativeArray<int>) and SetColors(NativeArray<float4>) would be also awesome).
    It's a bit hard to count bytes and pointers.
     
  9. PetrS

    PetrS

    Joined:
    Feb 10, 2014
    Posts:
    2
    +1 for the above mention of unmanaged getters - GetXXX(NativeArray<T>).

    The copy-free internal data getters would be ideal (mentioned as "under consideration" in the doc), but if it turns out they are not feasible, a way to still access data without going through managed memory (i.e. just native->native copy) would be highly appreciated.
     
  10. Carpet_Head

    Carpet_Head

    Joined:
    Nov 27, 2014
    Posts:
    107
    Is there no way to get the vertex buffer as a NativeArray<float3>? even with a memcpy, it would be fine
     
  11. alexnown

    alexnown

    Joined:
    Oct 25, 2018
    Posts:
    20
    Аre there any examples with using SetIndexBufferData api?
    Tried it for setting triangles, but only SetIndices works correct.
    Code (CSharp):
    1. //Not correct, mesh.triangles array still has zero length
    2. mesh.SetIndexBufferParams(triangles.Length, IndexFormat.UInt16);
    3. mesh.SetIndexBufferData(triangles, 0, 0, triangles.Length);
    4.  
    5. //Correct way set triangles from NativeArray<ushort>
    6. mesh.SetIndices(triangles, MeshTopology.Triangles, 0);
     
    MUGIK and OldLegWig like this.
  12. OldLegWig

    OldLegWig

    Joined:
    Mar 18, 2018
    Posts:
    81
    Seconding this. Documentation is a bit lacking. Verts seem to update fine but triangle array is empty.
     
    Last edited: Sep 6, 2019
    MUGIK likes this.
  13. francois85

    francois85

    Joined:
    Aug 11, 2015
    Posts:
    717
    My wish for the meshAPI is a more complete function set. If I compare it to something like maya MFnMesh you can see the difference. I know Unity is not a DCC but I want it to be one :)

    Mesh function set
    https://download.autodesk.com/us/maya/2011help/API/class_m_fn_mesh.html

    It would also be awesome to have some sort of Jobs iterators for meshes
    IJob...For<MeshVertex>
    Ill post mayas API below as a example of what I mean. Not necessarily the best but one im familiar with. Just my 2c

    Mesh Iterators

    https://download.autodesk.com/us/maya/2011help/API/class_m_it_mesh_vertex.html

    https://download.autodesk.com/us/maya/2011help/API/class_m_it_mesh_polygon.html

    https://download.autodesk.com/us/maya/2011help/API/class_m_it_mesh_edge.html
     
    Last edited: Sep 17, 2019
  14. Nothke

    Nothke

    Joined:
    Dec 2, 2012
    Posts:
    51
    I tried using a custom vertex struct with Mathematics' half3 and VertexAttributeFormat.Float16, but I get

    ArgumentException: Invalid vertex attribute format+dimension value (Float16 x 3, data size must be multiple of 4)

    ..But it works with float3, which is a multiple of 3.. So why wouldn't it work with 3 Float16s?

    Also, if I put anything but 3 dimensions in VertexAttributeDescriptor(), Unity crashes. I guess this is very bad :|

    Code (CSharp):
    1. using UnityEngine.Rendering;
    2. using Unity.Mathematics;
    3. using System.Runtime.InteropServices;
    4.  
    5. [StructLayout(LayoutKind.Sequential)]
    6. public struct Vertex
    7. {
    8.     public half3 pos;
    9.     public half3 normal;
    10.  
    11.     public static VertexAttributeDescriptor[] GetVertexAttributes()
    12.     {
    13.         return new[]
    14.         {
    15.             new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float16, 3),
    16.             new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float16, 3),
    17.         };
    18.     }
    19. }
     
  15. Jes28

    Jes28

    Joined:
    Sep 3, 2012
    Posts:
    415
    half3 = 6 bytes - not multiple of 4
    float3 = 12 byte - it is multiple of 4

    That is what message says

    try to use half4 = 8 bytes and ignore 4th element or use for something else

    May be this will not allow you to use half 4 :(
     
    Nothke likes this.
  16. Nothke

    Nothke

    Joined:
    Dec 2, 2012
    Posts:
    51
    Ahh bytes! The error message should say "bytes" instead of just "data size" which is confusing.

    Yup, I just changed everything to half4 and Unity just crashes.

    Strange since their example uses Vector3 (as 3x Float32), 2x ushort (as 2x Float16) and Color32 (as 4x UNorm8), so obviously conversion should be smooth
     
  17. Jes28

    Jes28

    Joined:
    Sep 3, 2012
    Posts:
    415
    I think you need to fire a bug about crash for half4
    I thought even to use some day UNorm4 as position because I dont need precision bigger than 256 for each component.
     
  18. Nothke

    Nothke

    Joined:
    Dec 2, 2012
    Posts:
    51
    Filed it!
     
    Jes28 likes this.
  19. OlegPavlov

    OlegPavlov

    Joined:
    Jun 22, 2014
    Posts:
    8
    This update is FIRE!
    My mesh setup time reduced almost 16 times!

    When i call SetBuffer<T> does it just pass buffer to graphics api and don't store it? If it is it would be great! That would mean that user holds the data, and can do anything with it.

    But i still have my main thread filled with mesh setups.

    We'd like to see this fine vertex precision controls in Model Importer, so we could optimize meshes from editor without writing any code.
     
    Jes28 likes this.
  20. OlegPavlov

    OlegPavlov

    Joined:
    Jun 22, 2014
    Posts:
    8
    bugs i found in 2019.3.0b3:

    SetIndices(calculateBounds: true) - doesn't calculate bounds (doesn't really bother me)

    SetVertexBufferParams - position of attribute inside layout array doesn't define struct layout, it looks like the order is predefined based on attribute type

    if using Format.SInt8 for VertexAttribute.Position Mesh.RecalculateBounds() crashes editor
     
    Last edited: Sep 23, 2019
  21. rsodre

    rsodre

    Joined:
    May 9, 2012
    Posts:
    189
    Not sure if this is the place, but would be nice to have PLA (Point Level Animaiton) support on Unity.
    I use Cinema 4D for modeling and animaiton, and the lack pf PLA limits a LOT the animation tools I can use.
     
  22. DrSeltsam

    DrSeltsam

    Joined:
    Jul 24, 2019
    Posts:
    6
    I love the new mesh API so far, this is really a major improvement! But it would be great if we could also call SetVertexBufferData() with a pointer to unmanaged memory (with an option to set the element size manually), same for SetIndexBufferData(). Something like SetVertexBufferData(void* ptr, int elemSize, int length, ...). Or direct access to InternalSetVertexBufferData() alternatively :D

    Currently my "workaround" is to create a NativeArray from my pointer temporarily (NativeArrayUnsafeUtility), assign an AtomicSafetyHandle (otherwise the mesh API doesn't like my NativeArray), then set the vertex buffer data and release the safety handle again. It works like a charm, but it would be nice if I don't have to take these extra steps. Apparently SetVertexBufferData() just gets the underlying pointer from the NativeArray...
     
    OlegPavlov likes this.
  23. TheZombieKiller

    TheZombieKiller

    Joined:
    Feb 8, 2013
    Posts:
    45
    Could we also get List<T> and T[]-based overloads for SetBoneWeights? Currently there's only a NativeArray<T> version, meaning I need to do this:

    Code (CSharp):
    1. using (var bonesPerVertex = new NativeArray<byte>(BonesPerVertex.Count,     Allocator.Persistent))
    2. using (var boneWeights    = new NativeArray<BoneWeight1>(BoneWeights.Count, Allocator.Persistent))
    3. {
    4.     MemoryUtility.CopyToNativeArray(BonesPerVertex, bonesPerVertex);
    5.     MemoryUtility.CopyToNativeArray(BoneWeights,    boneWeights);
    6.     mesh.SetBoneWeights(bonesPerVertex, boneWeights);
    7. }
    Which isn't super ideal. It'd also be nice to have a SetBindPoses method, as currently only the array-based property setter exists.
     
  24. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    207
    I think you can also use Allocator.Temp here.
     
    TheZombieKiller likes this.
  25. o1o1o1o1o2

    o1o1o1o1o2

    Joined:
    May 22, 2014
    Posts:
    29

    Can you please look at this thread https://forum.unity.com/threads/how-to-cache-mesh-getnativevertexbufferptr.762197/#post-5075690 i have a question about what does GetNativeVertexBufferPtr() do
     
  26. Carpet_Head

    Carpet_Head

    Joined:
    Nov 27, 2014
    Posts:
    107
    We are having some trouble with the new buffer API's and mesh bounds:

    Code (CSharp):
    1. VertexAttributeDescriptor[] vertexLayout = new[]
    2. {
    3.    new VertexAttributeDescriptor(VertexAttribute.Position),
    4.    new VertexAttributeDescriptor(VertexAttribute.Normal)
    5. };
    6.  
    7. MeshUpdateFlags flags = MeshUpdateFlags.DontValidateIndices;
    8.  
    9. meshToPopulate.SetVertexBufferParams(finalNumVertices, vertexLayout);
    10. meshToPopulate.SetVertexBufferData(vertexBuffer, 0, 0, finalNumVertices,0,flags);
    11.  
    12. meshToPopulate.SetIndexBufferParams(3 * finalNumTriangles, IndexFormat.UInt32);
    13. meshToPopulate.SetIndexBufferData(triangles, 0, 0, 3 * finalNumTriangles, flags);
    14. meshToPopulate.SetSubMesh(0, new SubMeshDescriptor(0, 3 * finalNumTriangles), flags);

    Take this code snippet for example. I would expect that, because we do not set MeshUpdateFlags.DontRecalculateBounds, the mesh bounds would be calculated. However, they aren't. Is there a reason for this?
     
  27. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    151
    Guys, did you find a solution to this?
    My triangles array is also empty, while vertex buffer data sets correctly.

    UPD
    Fixed!
    So to make it work you need to do setup in this order:
    Code (CSharp):
    1. _mesh.SetVertexBufferParams(vertexCount, MeshLayout);
    2. _mesh.SetIndexBufferParams(indexCount, IndexFormat.UInt32);
    3. _mesh.SetIndexBufferData(indexBuffer, 0, 0, indexCount, MeshUpdateFlags);
    4. _mesh.SetSubMesh(0, new SubMeshDescriptor(0,indexCount, MeshTopology.Triangles), MeshUpdateFlags);
     
    Last edited: Oct 24, 2019
  28. Thrawn75

    Thrawn75

    Joined:
    Nov 16, 2014
    Posts:
    2,240
    Any chance to set the SortingOrder when using DrawMesh?
     
  29. Thrawn75

    Thrawn75

    Joined:
    Nov 16, 2014
    Posts:
    2,240
    These new APIs are super useful addition and boosts any procedural generation. Very happy to see improvements in this area coming finally!
     
  30. vx4

    vx4

    Joined:
    Dec 11, 2012
    Posts:
    101