Search Unity

[RELEASED] DirectX 11 Grass Shader

Discussion in 'Assets and Asset Store' started by Nonakesh, Aug 17, 2015.

  1. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Hey,

    To just render grass following the normal, you could use the shader setting "Follow surface normals", but that still won't make the interaction system work.
    The main problem is, the interaction system works by using a camera that renders all interaction objects to a render texture, then telling the shader which part of the world this texture currently represents (world x, world z, width, height). Changing this to support arbitrary rotations would be.. difficult. To say the least. You'd have to map the grass blade position to the texture (which may be rotated in any direction), then figure out how the grass should actually move, based on that. For example, the camera could be horizontal to the grass.
    Honestly, I think using the interaction system for something like this would simply not work.
    Here's what I would do:
    • If you really need complex, dynamic interactions, use a interaction texture, change it via scripts and raycasts. That's still gonna be complex, but doable, I believe. Performance might be difficult.
    • Modify the shader to read an array of points that will push the grass away, that way you can still handle multiple objects, you might even pass a radius and strength for more dynamic effects. That's probably by far the easiest solution.
    In case you want to see how the interaction works, thats all in the Grass.Geom.hlsl file.

    I hope that helps! I'd be happy to help if you have any other questions.
     
  2. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Thank you for your reply!

    I am already using "follow surface normals" for the grass, and it works great, the grass itself looks fine at all orientations.

    I just hadn't noticed the issue with grass displacement up until now.

    The only thing that might, hopefully, help me here is tha I do *not* need complex interactions.

    All I want to do is have an area around certain objects that completely excludes grass, such as in this image:

    https://imgur.com/yUr02v7

    You can see that the fire has a circular exclusion around it. Without this, it can be very hard for the player to interact with items on the ground, etc, due to the thick grass cover.

    Would there be any easier way of adding simple grass exclusion?

    If not, I'll just have to leave it as is for now, and look at it when I get more time, it sounds extremely complex.
     
  3. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    In this case I would use a density texture instead. If you don't need procedural generation I would recommend using the grass painter for that, although I'm not 100% sure if it will work with spheres...
    You could create the density texture in another program. Each color channel (including alpha) represents one of the 4 grass types, so im case you only want to remove all grass in certain spots, you could create a black and white texture with black spots whereever you want to remove grass.

    In case you are using procedural generation, it's basically the same process, but via script. Make sure your mesh has UV coordinates.
     
  4. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Hi,

    That is looking slightly more promising I am using procedural generation, yes.

    I'm not too sure what you mean about using a density texture though. Is there an example somewhere in the code I could look at?

    I created my existing grass displacement objects using the examples in the demo scenes, but since I am using procedural generation, I would need some kind of script example?

    Thanks a lot for your help!
     
  5. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    The density texture is what the grass painter creates. I'd recommend you try it on a regular unity plane, just put the material in a Grass renderer and open the grass painter. There you can automatically create a density texture. Try painting around and see how the texture changes.
    You could also check the documentation for the grass painter.
     
  6. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Also in case you never changed textures in Unity before, you can do that with Texture2D.
    Another thing that can help a lot is that you can find the texture coordinate of a Raycast, then use that coordinate to change the texture. It's all a bit tricky, but this should work on all kinds of surfaces.
     
  7. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Thanks for your reply. I took a look at the grass painter, and I doubt it will work for my use case. I am already using a density texture to create "patches" of grass, and I can't seem to figure out how I could procedurally use that system to exclude specific objects.

    IE, the player can randomly create and destroy objects on the ground during the game, so I'd need to recreate the texture each time?

    Would there be any way to "cheat", by creating, say, an invisible sphere around the object on the ground, and then masking out the grass within that sphere?

    I'm also looking into your other suggestion about sending an array of points with a radius to the shader. So, basically I would send the position of a specific object to the shader, along with a radius, and the grass would not render that point?

    That makes sense. Do you know which file I would need to begin modifying to add that feature?

    Thanks for your help on this.
     
  8. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Yes, for dynamic changes, you'd have to change the texture on the fly. It's not quite as bad as recreating the texture, but still bad most likely.

    The blades of grass are created in the GrassGeom.hlsl file, that's probably the only file you will need. I would try to copy how the density texture can lead to blades of grass not being rendered. Then you'll just have to find a way to pass the data to the shader. I've never used it myself, but you should be able to pass a ComputeBuffer to the material and use it in the shader.
     
  9. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Thank you, I'll take a look at that in the near future! Hopefully I can figure something out!
     
    Nonakesh likes this.
  10. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Hi,

    I have this system almost working!

    Your directions were very good. I have created a texture, and I am modifying it at runtime to exclude grass from around certain objects.

    This is very fast, and works great! I only need to modify the texture when an object moves, so the performance isn't an issue.

    The only problem I have now is that I am using a terrain system with multiple connected blocks, and so I need to add instancing to the texture that I have added so that I can exclude grass on a per-terrain-block basis, and not have the same texture used for all terrain blocks.

    This works when I apply the grass shader directly to a mesh:


    Code (CSharp):
    1.            
    2.  robject1.GetComponent<MeshRenderer>().GetPropertyBlock(_propBlock);
    3.  _propBlock.SetTexture("_MYTEXTURE", exclusiontexdefault);
    4.  robject1.GetComponent<MeshRenderer>().SetPropertyBlock(_propBlock);
    5.  
    However, it doesn't work when I use a "grass renderer" object.

    This is not a massive priority, but is it possible to use getpropertyblock with the grass shader?
     
  11. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    I'm uploading a version with SetPropertyBlock to the asset store right now. I didn't have time to test it myself, but it's just passing the block to Graphics.DrawMesh, so it should be fine, I think.

    I also didn't know how to implement GetPropertyBlock, I think I would need some internal data for that, so just create a new block and pass it to SetPropertyBlock.

    The update should be on the asset store in the next few days! :)
     
  12. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Excellent, thank you very much!

    I'm using an older version of the grass system (I haven't updated in a while since I have made so many changes to it). Do you think it would be easy to port just the getpropertyblock changes back, or would I need to completely update the asset?
     
  13. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Yeah, I think it should be quite easy. There are only two or three changes in the file. If you didn't make changes to the grass renderer, you should even be able to replace the file without any problems, I think.
     
  14. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Excellent, I'll look into that in a few days, thank you!

    Which file is it that needs to be changed, grassgeom.hlsl? Is that the only one?
     
  15. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Actually, it should only be GrassRenderer.cs
     
  16. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Hi, I made those changes, and it seems to be working great! Thanks for all of your help!
     
  17. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    I'm glad I could help! :D
     
    PhoenixAdvanced likes this.
  18. paulojsam

    paulojsam

    Joined:
    Jul 2, 2012
    Posts:
    575
    Hello! im trying to render grass to a probuilder plane mesh but in webgl it comes out pink. any ideias please?
     
  19. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    WebGL does not support compiling my shader. You could play around with grass fallback, but if WebGL is your main platform I would honestly recommend not using my grass shader.
     
  20. paulojsam

    paulojsam

    Joined:
    Jul 2, 2012
    Posts:
    575
    thank you :)
     
  21. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    300
    This is how it looks in deferred rendering mode in 2021.3.x, did I miss anything. So I have to use forward-only renderer I guess, otherwise it's looking completely broken.

    upload_2022-6-13_18-57-0.png

    Additionally, there are several prefabs and scripts missing in the examples. Are you aware of that?
     
  22. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Is this in URP or builtin? The shader only supports URP forward rendering, but it should work with buildin deferred as expected. If it doesn't I'll have to look into it.

    I wasn't aware of the missing prefabs. I'll have to check that too.
     
  23. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    300
    It's the built-in pipeline.
     
  24. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Alright. For now I'd recommend you use the Forward Only version of the shader, as you said.
     
  25. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    300
    Ok thanks.
     
  26. MKayJay

    MKayJay

    Joined:
    Oct 8, 2013
    Posts:
    11
    Hey :)
    A few questions, if you don't mind?
    Do you have any plans to support Deferred rendering with URP? This asset is currently the only one holding me back from switching to deferred.

    Secondly, I'm using the grass procedurally. I create a displacement texture at runtime, and up until now, it has worked like a charm.
    I recently decided to reduce the size of my chunks, for other -not grass related- performance issues.
    Now, after I've done that I expected the grass to continue working, but, now I get grass floating in mid-air. I know I've had the issue before, where I had to rotate my displacement texture to fix it, but this time this does not appear to be the case.
    My terrain is split into several meshes, and I do a displacement texture for each mesh (chunk). After the chunks are created, I do static batching on all the chunks. I was considering if that could affect things, but I then wonder why it didn't before? (Btw, if I go back to my original size, I do not have an issue)
    I just wanted to ask, if you know any common causes for floating grass?
    Thanks :)
     
  27. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Hey!

    At the moment I'm not planning to support deferred rendering in URP. Is it not possible to use a forward rendered shader in deferred URP like in builtin?

    The only reason I can think of is that the Nature Mesh Filter has the wrong mesh in its cache. Try resetting it with the ResetCache() method. You could also try to add the grass material directly to your mesh, if you're already using procedural generation that should be fairly easy: Create a copy of your terrain mesh, apply the material and you're done. If you're using some kind of LOD, keep the grass mesh at maximum LOD to prevent popping.
     
    MKayJay likes this.
  28. carking1996

    carking1996

    Joined:
    Jun 15, 2010
    Posts:
    2,609
    So how does lighting work here? No matter what setting I use, one side of the grass is pretty dark. It looks good otherwise, but is there a way to make it look closer to the forward-rendering shader that's generally lighter?
     
  29. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    That's because Unitys deferred rendering isn't great for something like thin blades of grass, it's missing the subsurface scattering. I'd recommend either trying to balance it out with an additional directional light from the opposite direction, or using the Forward Only version of the shader, so you can use all the lighting settings of the shader.
     
  30. carking1996

    carking1996

    Joined:
    Jun 15, 2010
    Posts:
    2,609
    Dang! It looks great otherwise. Just wish there was a way to make those dark areas lighter.. no way to do it artificially?
     
  31. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Except for a second light, I can't think of a good way. You could add emission to the grass, but that way the light side would also start to glow. Honestly, I was fairly disappointed myself when I first created the deferred version. It's possible I missed something, because the grass appears darker than regular meshes, but as the shading in deferred rendering happens in Unitys rendering code, there's really nothing that I could have done wrong.

    Another thing that could solve the problem is overwriting Unity's deferred rendering shaders. That's possible, but it would be complete overkill and I don't know what other problems it might cause.
     
  32. carking1996

    carking1996

    Joined:
    Jun 15, 2010
    Posts:
    2,609
    Here's from a quick Google. Other people have had the problem. It seems you can mess with the ambient light it takes in. Though it isn't perfect it seems, but I'd give it a shot.

    Shadow too dark in custom deferred shader - Unity Forum
     
  33. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    I finally figured out what was wrong! It wasn't the thing you suggested, I was already doing the same thing as Unity's standard shader, so ambient light was already included. I decided to go through the entire deferred rendering stuff again and there were some slight differences (I've fixed those too, but I don't think they did anything).

    Anyways, the problem actually turned out to be surprisingly trivial, I simply missed that the deferred shader pass had to be marked with "#pragma multi_compile_prepassfinal". After that the ambient light was rendered light everywhere else.

    The shader had that problem for years now, so thanks for nudging me to look into it again :D

    I also figured out your problem along the way: You simply have to select the grass object and open the material editor. Then the editor can update all material settings for deferred rendering and the problem will vanish.
     
    carking1996 likes this.
  34. carking1996

    carking1996

    Joined:
    Jun 15, 2010
    Posts:
    2,609
    Great! I'm not the best with shaders but I'll see if I can add that in the correct spot :)
    Edit: Only took a second. Looks great!
     
  35. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Nice! I've also uploaded the update, so it should be available on the asset store within the next few days.
     
  36. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    300
    Great, thank you! Much appreciated!
     
  37. hermitmode

    hermitmode

    Joined:
    Sep 15, 2020
    Posts:
    43
    Is it an easy upgrade from the 2017 version? I am having lighting issues at certain levels of directional light (flicking between black and shaded), would this be fixed in the most recent version?
     
  38. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    I'm guessing that's a 1.x release? I'm not sure how much work migrating would be, but it shouldn't be too bad. The lighting issue should be fixed (and if it's still there you can post here and I'll look into it!).

    The main difference in the 2.x releases is the GrassRenderer component. It's a way of rendering grass without having to duplicate the mesh. It is completely optional, unless you want to use some mesh processing features.
    There may also be some changes for lighting and density, so you'll probably have to do some fine tuning for each grass material, but most of the material properties should stay the same.
     
    hermitmode likes this.
  39. radiantboy

    radiantboy

    Joined:
    Nov 21, 2012
    Posts:
    1,633
    does this work on HDRP yet?
     
  40. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    No, at the moment it supports builtin and URP.
     
    radiantboy likes this.
  41. robert-nally

    robert-nally

    Joined:
    Mar 5, 2014
    Posts:
    76
    Hi,

    I recently upgraded my project from 2019.2 to 2019.4.40 and now I'm seeing these errors for the grass shader. Any idea on how to fix them? I've been using the built-in renderer.

    Oh, also, I did update the package cause I thought that might resolve the issue, but they were still there.
     

    Attached Files:

    Last edited: Nov 4, 2022
  42. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Just delete the GrassHDRP.shader file, that should remove the errors. The errors don't really do anything, except fill up the console, the rest of the package should work as expected.
     
  43. robert-nally

    robert-nally

    Joined:
    Mar 5, 2014
    Posts:
    76
    ok cool, thank you! I figured that was the case, but I wanted to make sure.
     
    Nonakesh likes this.
  44. hermitmode

    hermitmode

    Joined:
    Sep 15, 2020
    Posts:
    43
    I ended up upgrading but saw some performance and visual issues which must not make sense but nevertheless occurred so I rolled it back to the 1.x release I had been using previously.
    I understand that it is obsolete and its a long shot to get assistance due to this but considering the lighting issue seemed to be missing from your updated version, you might have an idea of where I would have to look or what I would have to edit to deal with the issue shown below. Any assistance is greatly appreciated.
     
  45. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Hey, yes I believe performance got slightly worse with additional features. Or at least some newer features (like randomly oriented blades of grass) cost more performance.

    As for the lighting problem, I remember fixing that problem, but unfortunately I have no idea what the fix was. I'd guess that it's a problem where Unity changed parts of their internal lighting code. Those errors are typically quite hard to find.

    The only thing I could recommend is that you try optimizing the new shader version: https://stixgames.com/grassshader/documentation/performance-optimization

    I'm sorry I can't be more helpful.
     
  46. hermitmode

    hermitmode

    Joined:
    Sep 15, 2020
    Posts:
    43
    Thank you for your time, I understand its on me for wanting to use obsolete versions. I will look into the shader route, thanks.
     
    Nonakesh likes this.
  47. radiantboy

    radiantboy

    Joined:
    Nov 21, 2012
    Posts:
    1,633
    how do I get this working in URP?
     
    khos likes this.
  48. khos

    khos

    Joined:
    May 10, 2016
    Posts:
    1,487
    Good idea/question :) I'm keen to know
     
  49. Nonakesh

    Nonakesh

    Joined:
    Aug 27, 2011
    Posts:
    576
    Just switch the material from "Stix Games/Grass" to "Stix Games/Grass URP" and it should work.
     
    khos likes this.
  50. khos

    khos

    Joined:
    May 10, 2016
    Posts:
    1,487
    Awesome! Many thanks
     
    Nonakesh likes this.