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
  4. Dismiss Notice

Resolved Can you access the last vertex in the shader in an elegant manner?

Discussion in 'Shaders' started by CinnamonCereals, Jan 24, 2022.

  1. CinnamonCereals

    CinnamonCereals

    Joined:
    Jan 19, 2022
    Posts:
    23
    Hello, I'm trying to make a cloth like-material. In order for me to do that, I want all the vertices to have the same distance between each other as the distance was when the game started, all the time (in a static state, unaffected by physics)

    Currently how I do it I pass 2 arrays from the monobehaviour to the shader every frame.
    • One representing the array of vertices the mesh had when the game started.
    • Second representing the array of vertices the mesh has this current frame.
    I use the SV_VertexID attribute to get the vertex ID in order to compare the distance between the current last 2 vertices, and the start last 2 vertices of the current index (if it's bigger than the start distance, update the current distance). I modify the current vertices to be the distance of the start vertices if needed.

    Every frame I pass two arrays of 1000 elements each. Even tho this does the work, I don't find this to be very elegant/performant. Is there a better way to do this? (Side note: this method also bothers me because I have to limit the vertices on my mesh to not pass 1000 as I understood 1024 is the limit you can pass) I'm not looking into using compute shaders as I'm in the mobile genre and not all GPUs support it

    EDIT: At this point I'm really wondering if there's any point in doing this in a shader anymore
     
    Last edited: Jan 26, 2022
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    Store the original vert positions into a UV channel so that you don't have to send it every frame.

    Also as of 2021.2 you can directly modify the vertex buffer from a computer shader. So you don't have to keep sending mesh data to the GPU. https://github.com/Unity-Technologies/MeshApiExamples
     
    CinnamonCereals likes this.
  3. CinnamonCereals

    CinnamonCereals

    Joined:
    Jan 19, 2022
    Posts:
    23
    Altho it sounds interesting, I don't quite understand your first solution. (I'm new to shaders). Could you give me a quick example? (I'm only using code)

    I hesitated on using compute shaders but I think I'll give it a try thanks to you
     
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    UV channels are not just for UVs. They can hold whatever array of float4 data that you want, and will always match the length of your vertex count. So when you create the model you can grab your vertex position array and assign it to a UV channel, there are up to 8 uv channels. Then in compute or regular shader, you can access that info just like you would the texture uv coordinates.
     
    CinnamonCereals likes this.
  5. CinnamonCereals

    CinnamonCereals

    Joined:
    Jan 19, 2022
    Posts:
    23
    Thank you, I figured compute buffers are a better choice for my situation. Do you think it's too expensive to send a compute buffer from the mono to the shader too often?
     
  6. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    It depends on the size of the buffer, bandwidth of the hardware and already used up bandwidth by the game.
    Ideally if you do not need the CPU side to see the changes being made to the mesh, then it's best to try and keep it all on the GPU. But it's fine to be running a compute job each frame for sure, just try to minimize the amount of data you need to send.
    By having the original vertices stored in a UV channel, you can avoid having to send that information every frame, it'll just always be there to use from the UV channel.
     
    CinnamonCereals likes this.