I have hundreds of trees that are static objects and I want their color to vary randomly. I tried creating a shader graph that does this by using the Object Position information to randomize a Hue value. However, this does not seem to work with static objects (works in editor mode, but not in play mode). The world position also doesn’t work as that will adjust hue by pixel which creates undesired gradients. I then tried using the InstanceID node as the basis for the randomization, but that does not seem to work at all (apparently only works with Graphics.DrawMeshInstanced API call).
Any ideas how to solve this? I thought about using a script to randomize value and pass that to the material, but I am unsure if that would be the correct way for such a high amount of objects. Is there a known “best” solution for this problem? I imagine needing to randomize color for materials is a very common use case.
Hi @Bearsauce,
Batching merges your meshes, so things like Object Position won’t work.
And InstanceID, even with Batching disabled, will only be predictable if you control the rendering with calls to Graphics.RenderMeshInstanced.
Now, can you share a bit more information, such as your target platform(s), render pipeline, Unity version?
If you’re using URP or HDRP, you may get better performance and more freedom by using the SRP Batcher and/or GPU Resident Drawer.
1 Like
Hey Fred,
Thanks for the reply! I am on Unity 6 with URP and targeting PC (aiming to run on most modern hardware). The game is a low poly open world game with procedurally generated environments (using mesh-based prefabs, not Terrain). It is expected that there will be a lot of environment visible on the screen at any given time (= no indoors or closed spaces).
I’m not very knowledgeable about the graphics side so while I have heard about those terms, I don’t know about their ins and outs. I can see that currently I have SRP Batcher enabled and GPU Resident Drawer disabled in the project. What would be a good way to solve the problem if I am using either of these?
The first thing I am wondering if this is something that would be best solved within the shader graph (although it doesn’t feel possible due to the objects being static), or if having script randomizing the value and creating hundreds of material instances is ok or if having a huge amount of preset material (of the same shader graph) variants would be best OR maybe something I haven’t thought about.
1 Like
Hey,
I took the time to ask our experts and here are some suggestions.
- You should disable Static Batching in your Project Settings (Player Settings).
- And enable GPU Resident Drawer (Instance Drawing).
- You may then create 20 - 30 materials with some randomized parameters each and performance should be fine.
- Double check with RenderDoc if you can to make sure objects sharing the same material are rendered using a single DrawInstanced.
I would add that with GPU Resident Drawer (GRD), you may use the Object Position as the “seed”. If objects aren’t moving, this is an easy way to randomize things within your graph, without duplicating materials.
Here I’m using a Custom Interpolator, so the seed is only generated per-vertex.
The Hash31 comes with Shader Graph Samples by the way.
And as you can see in the Frame Debugger, all 10.000 objects are rendered in this Hybrid Batch Group.
Don’t use the InstanceID Node in this context. It’s not predictable since instances ordering will change based on the view.
Should you want to have more control over that seed, you could also expose a float property.
This makes more materials, but no seed generation in the vertex shader.
So depending on the number of unique seeds and number of vertices in meshes, performance may vary.
You then need some C# to duplicate materials, assign a different seed to each, and randomly assign them to renderers.
Hope this helps!
2 Likes
Wow, thank you Fred for the in-depth answer! I learned a bunch of new stuff. Everything looks good after following these instructions and using the position as the seed with the custom interpolator. I’ll do some performance testing when I have more things in place, but at least currently there aren’t any performance issues. Thanks again!
1 Like
Hey Fred, after having the GPURD enabled for a few days, I wanted to ask if you are aware of GPURD causing editor leak issues and if there are known solutions for them? I couldn’t find good information about this.
So, after enabling GPURD, I started getting log warnings: “[Worker0] Internal: There are remaining Allocations on the JobTempAlloc. This is a leak, and will impact performance”. I toggled on the related diagnostic switch and got 2 different stack traces:
The issue comes up very frequently during many different editor actions. For example when saving a scene, or when editing a prefab 3d model or when opening a project folder with these prefabs that don’t have a 3d preview yet (I can see the assets not having previews, then a somewhat long wait, followed by Worker0 log messages before the previews appear). I’ve tried disabling most objects in my scene, trying to add GPU instancing to materials (dunno if this has any significance but thought I’d try) and disabling all my renderer and volume effects. These did not fix the issue. Turning GPURD off does fix the issue though. Is this a known issue with GPURD?
My editor performance is still good despite this, but I am worried if this issue is something that will transfer to builds also. In case there are no known solutions to this issue, I wonder if you have suggestions what could be a good secondary solution to the original topic if GPURD is not used?
P.S. I also encountered another issue with GPURD & mouse selection cycling that I posted about elsewhere (https://discussions.unity.com/t/unity-6-gpu-resident-drawer-breaks-scene-picking-mouse-click-to-select-in-scene-view). It is not a big issue, but thought I’d mention it also.
Hi,
it seems this was fixed in 6000.0.35f1.
- Editor: Fixed a memory Leak warnings message fixed when creating material + GPU Resident Drawer. (UUM-90039)
Since I read in the other post that you’re on 6000.0.29f1, can you try and confirm it’s fixed with the latest version?
Thanks
Ah, should have checked the latest version! I can confirm that at least after a few hours of using the editor, the leak issue hasn’t happened. The selection cycling issue still happens, but that’s so minor that I don’t mind it. Thanks again!
1 Like