Search Unity

Why are my GPU instanced objects black and am I doing this grass the right way?

Discussion in 'Shaders' started by tcz8, Apr 1, 2017.

  1. tcz8

    tcz8

    Joined:
    Aug 20, 2015
    Posts:
    504
    Long story short:
    2D Grass shader > vertex animated > can't use batching afaik because pivot > Trying gpu instancing > Instance is all black > Can it be fixed? > Should I rethink the whole thing?

    Wated features:
    -Actuall grass, not tiles
    -Lots of it
    -Wind simulation
    -Can be displaced by objects moving through it

    Long story:
    I am making a shader to animate 2D grass, all features are implemented. Worked great until I implemented a render texture to make the grass fold when objects move through it.

    Had to disable batching to get things to work (vertex animated using offsets afaik I need individual pivot points... is there a way around this?) ...batching completely screwed my performance so I got GPU instancing working on my sprites with the code bellow and HURRAY! It works and it doesn't mess with pivot points so my vertex animations work! BOoo! the instances are black.

    Here is what I get:



    Honestly, I really dont care how I fix this. In the end, I need to cover my screen with grass. Right now I have about 3500 of those sprite objects and with batching disabled a lot of preformance is lost just for grass. I hope gpu instancing can fix this but I am not even sure I am doing this thing the right way.

    I need help fixing this and/or figuring if I should be doing this some other way.

    Thank you!
     
    Last edited: Apr 16, 2017
  2. tcz8

    tcz8

    Joined:
    Aug 20, 2015
    Posts:
    504
    Any suggestions? Anyone? :(
     
  3. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    For something like this, I usually make one big set of planes and store the pivot position (excluding the height) in the second set of uvs. Then the whole thing can be attached into one big object in the modeling tool. Since you can retrieve the pivot position from the second set of uvs, you can still wave and rotate the object around the pivot in the shader.

    This is for a fixed amount of decals in the scene. For a larger amount, you can use a sliding window. Similar approach, but now you fill a square instead of the actual positions. Say the square is 50 by 50 units. Then in the vertex shader you move the decals in 50 unit increments to position them in range of the current view. The height can be retrieved from a texture, but that does mean you require shader model 3 to access a texture in the vertex shader. Also don't forget to adjust the bounding box of the mesh, so it doesn't get frustum culled.

    Not the easiest thing, but fast and very flexible.
     
  4. tcz8

    tcz8

    Joined:
    Aug 20, 2015
    Posts:
    504
    @jvo3dc Very good suggestions.

    One thing I am not clear about, you say you store the pivot position in the 2nd uv so you can use them later? How does that work and does it allow your grass to batch?

    I assume you use a script to set a value in the shader for each plane of grass? but I am not sure how you manage to wave each blades of grass individually once they are batched into one mesh and under a single pivot point.

    Thank you for your help.
     
  5. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I actually do this in 3ds max. So it doesn't rely on batching. It's just a simple maxscript that copies the pivot position to the second uv. Then I collapse it in 3ds max before exporting. Imports a lot quicker into Unity too this way.

    You could also do it in Unity in a way that allows batching, but it will take a while for Unity to create all batching groups. If you are sure you want to render all of them anyway, it's more efficient to prepare that in a modeling tool.