Search Unity

Question Unity Terrain performances on Oculus Quest 2

Discussion in 'VR' started by Alixar, Nov 27, 2020.

  1. Alixar

    Alixar

    Joined:
    Mar 13, 2019
    Posts:
    50
    I am using Unity Terrain to create some basic landscape but I have the impression that the performance impact is significant (or at least, way more than I was expecting):

    1) This is the situation with a simple plane, this scene uses 4k tris, with a GPU at L2 the app time is 7.4ms

    2) This second scene uses 24k tris, the GPU goes to L3 with an app time of 9.5ms

    3) This third scene uses 24k tris but the plane is now textured, the GPU goes at L3 with a considerable load and the app time is almost 11ms:



    These are my terrain settings. I have used no trees or grass, it's just the terrain. All light is baked, shadows are disabled. LOD is set to 80 with a generous pixel error.

    upload_2020-11-27_20-9-51.png

    The scene is just: static skybox, 1 directional light (baked), 1 random floating monolith and the terrain 250x250x100.

    Is this amount of workload expected or am I doing something horribly wrong? With terrain in place I have just about 3ms of GPU budget left that doesn't sound too appealing.

    Thank you
     
    hippocoder likes this.
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yes, Unity terrain is expensive.

    But what is that FPS display you're showing there? That looks like it's providing some very interesting and useful details.
     
  3. Alixar

    Alixar

    Joined:
    Mar 13, 2019
    Posts:
    50
    It's a bit too expensive, I am preparing a repro project to file a bug as, after consulting with other people, it sounds like there might be something wrong and it shouldn't be so expensive.

    The tool is OVRMetrics and it's indeed very helpful for early detection of performance problems - such as the one I'm having - and super simple to use. You might want to read the explainer page as well as it details how to interpret all the various fields.
     
    JoeStrout likes this.
  4. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    How many layers are you using? Are you using normal maps?

    The unity terrain material samples 4 diffuse and normal maps. Using more than 4 layers causes the terrain to be rendered a 2nd time with blending for more four layers. That can be quite a lot for the Quest.
     
  5. Alixar

    Alixar

    Joined:
    Mar 13, 2019
    Posts:
    50
    As shown in the screencap, the performance is very poor even with no textures (no normal maps) and a single base layer. Meanwhile I filed a bug, I'll update this post when Unity support replies.
     
  6. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    Even if you only use one layer, the shader will perform at least 5 texture sample operations (6 if you are using instanced terrain).
     
  7. Alixar

    Alixar

    Joined:
    Mar 13, 2019
    Posts:
    50
    Then if that's the case, I'll have to find some other solution to landscape that doesn't eat up so much GPU time. Thanks for your input!
     
  8. HIBIKI_entertainment

    HIBIKI_entertainment

    Joined:
    Dec 4, 2018
    Posts:
    595
    Have you ensured that at this stage you've tuned you camera FOV and culling distance too?

    You will find performance drops with occlusion culling at this stage too, so if you have it, remove it.

    Also split your terrain into 4 and just run one segment you're looking at, see if there is a performance gain chance for asynchronous loading in one scene or using scene additives.
    If yes you might be able to look in that direction too.

    A recent game built on Unity Genshin Impact is certainly worth the research into, they attained 30km2 using the terrain system and so great async loading ideas. No VR in that case but It may help create and idea for a solution for you.
     
    gotiobg likes this.
  9. Alixar

    Alixar

    Joined:
    Mar 13, 2019
    Posts:
    50
    I have done several experiments with FOV and culling distance (which is currently very short at just 80m) but still the impact remains very high. I didn't split the terrain as it's just 250x250 with 0 objects on it, but I'll give it a try and split it in smaller chunks. Although an equally large terrain made in blender works absolutely fine, in fact for now I'm doing just that since I'm still prototyping.

    Thanks for your input.
     
    HIBIKI_entertainment likes this.
  10. HIBIKI_entertainment

    HIBIKI_entertainment

    Joined:
    Dec 4, 2018
    Posts:
    595
    You're most welcome, sorry to hear you still haven't found a suitable solution, I Will have another look myself at some of our work, because we're running 25km2 terrains at only 1.2-7ms no split, on either GPU/CPU. Granted we're not targeting the oculus here so it could be a chip architecture limit there.


    We've found negligible terrain tiling/Async uses until after certain sizes to especially if you're budgeting for calls/GPU bottlenecks.

    Terrain systems is certainly is tricky to balance.

    If look again at your terrain core defaults ( just your height data in.

    With everything solid, lights/shaodws at real-time, simple directional without post etc and just add in piece by piece your like pixel error. I've certainly seen massive increases in performance there just from going from 5-9 but then after more increases the gains just fall.

    But yeah, add your occlusion culling, camera culling etc in last, just to see the gains on cons on MS, FPS, Batches. There might be something you can tweak just a smidge.

    Occlusion culling I believe does add to the CPU and memory cost so you, may get a little more back by NOT using it in the case.

    Hope you find more luck anyway!
     
    Alixar likes this.
  11. jeremyco

    jeremyco

    Unity Technologies

    Joined:
    Oct 17, 2018
    Posts:
    38
    Hey, I work on Unity terrain and yes, there are significant performance issues on mobile platforms which we are actively investigating.

    Some questions for you:

    Could you describe how you are profiling?
    Is this from the editor or a build?
    If it's a build, is it release or dev?
    Are you using Oculus Link?
    Is this SteamVR, OculusVR or OpenXR?

    Have you tried cranking the pixel error all the way up? Could you share perf numbers with different pixel error values?

    Also, could you share the perf numbers you are seeing with instancing disabled vs enabled?

    For transparency, our current understanding of the problem is the device is CPU limited, due to our quadtree traversal algorithm which runs during culling. This is implemented in C++ and runs extremely fast on a desktop CPU, but a combination of memory access and the hot loop on mobile CPUs ends up causing issues.
     
  12. Alixar

    Alixar

    Joined:
    Mar 13, 2019
    Posts:
    50
    Hi Jeremy,

    Thanks for providing feedback, I opened a bug in Unity support and included my entire test project, so you should easily be able to run tests with one single click, to address your questions:

    1) The reduced framerate was very obvious (I added and patch of grass and I got nausea in seconds ;), first I did a quick run with OVR Metrics then I profiled using Unity profiler directly as on Mac I can't run RenderDoc
    2) Screenshot and numbers were from a build of course
    3) I did tests both in Debug and Release, the difference was negligible
    4) I am not using Oculus Link (not supported on Mac)
    5) When I posted it was OculusVR, I then ported the project to OpenXR with the same results, at that point I removed the terrain altogether.

    Anyway I got the impression that my app was GPU bound more than CPU bound in that specific example. For the other numbers: I haven't saved that branch and I moved ahead quite a lot. If there's a way to recover it from the bug I filed, I'd be happy to run those tests and report back the result.

    Thank you
     
  13. alttabb

    alttabb

    Joined:
    Dec 2, 2019
    Posts:
    3
    Hi, I am having very similar issues with terrain using Oculus Quest 2. At first, my terrain did not render at all although the mesh was there and my character controller was able to travel on it (I fixed it by turning off "Draw Instanced" in the terrain settings). However, now I have another issue where my Speedtrees do not render their shadow on the terrain mesh. It renders the shadows on the terrain just fine on my pc but whenever I build into the Oculus Quest 2 the shadows do not render on the terrain mesh anymore.
    Not sure if anyone have had a similar issue with shadows and terrains before but any feedback would be super helpful!
     
  14. Alixar

    Alixar

    Joined:
    Mar 13, 2019
    Posts:
    50
    Are you on URP with baked lights? It sounds like you might be trying to use real-time lights.
     
  15. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    Go with microsplat. It's free and runs well on mobile. It's a drop in replacement for the urp terrain shader if you buy the urp version. It got my game running on oculus quest 1 with it
     
    Last edited: Jan 13, 2021
    KawInt and kenlem like this.
  16. alttabb

    alttabb

    Joined:
    Dec 2, 2019
    Posts:
    3
    @Alixar You guessed it! my terrain was set to static and I had a baked lightmap assigned to it. I set it to non-static and re-baked my lighting. problem solved! now I can see my trees shadows on the terrain in VR. However, the performance is still pretty heavy on the headset.
    @larrydu88 Thank you for sharing the asset! I might give it a try once all my other task list items are checked :)
     
  17. jeremyco

    jeremyco

    Unity Technologies

    Joined:
    Oct 17, 2018
    Posts:
    38
    If anyone ends up trying microsplat, I'd be interested to hear back how performance compares to Unity built-in terrain

    @Alixar thank you for filing the bug! QA has already contacted me and we will continue working to improve the perf situation
     
  18. Alixar

    Alixar

    Joined:
    Mar 13, 2019
    Posts:
    50
    Thanks @jeremyco for your feedback, if you need my help just let me know!

    @unity_KKhaJ0VzNXLSlw I'm happy you solved it, but as you noticed the performance impact is quite significant on the headset. My suggestion is to use as many static objects as possible, disable real-time shadows and avoid real-time lights. I know it doesn't sound appealing, but there's only so much we can do on the headset :)
     
  19. eV-Interactive

    eV-Interactive

    Joined:
    Oct 25, 2016
    Posts:
    41
    We do a lot with terrain, and I'd suggest that if you want really good performance, you need to write your own shaders. Use the Unity shaders as a base, and strip out absolutely everything you don't use. Granted, our use-case is lots of relatively simple terrain, but we are running at full FPS on Quest 2 and - I have to say - it is awesome. For reference, we are using 8 texture units (a global color map, 4 splats used as details, splat control map, shadow map and... something else I forgot.) One light, fog, no normal mapping.

    Figure out what you really want/need, throw away everything else, and see where you are.
     
  20. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    I was the one who recommended microsplat in an earlier post.

    I can confirm that the default Unity Terrain shader for URP suffers extreme frame rate drops on the oculus quest even when I strip out the normal map from every texture.

    Microsplat on the other hand has a setting to turn off normals in the shader itself (which allows me to author terrain and potentially improve the terrain art in the future for releases on higher end platforms).

    An example of microsplat in action (with disabled normal maps) can be seen in this video:


    I can confirm that my game (with post-processing effects turned off) runs smoothly with microsplat terrain, but turns into a slideshow with standard unity urp terrain.
     
    Last edited: Jan 13, 2021
    P_Jong likes this.
  21. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461

    You know, reading this thread, if texture fetches of the normal array are pushing the quest beyond it's memory bandwidth limits, I could try generating the normal from the height map, which is already packed in with the diffuse. It's hard to say if the ALU cost of doing this would be worse than the memory access or not, but it should look pretty decent and not require any normal maps..
     
    jaydnwlsn likes this.
  22. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    So I did some experiments with this; basically I use the screen space derivatives and the height sample to generate a normal map. This is pretty cheap, and on Unity terrains I can do some shortcuts to swizzle the resulting normal into the correct space without doing any matrix multiplies. Results:

    Normal Mapping disabled:


    Using normal maps:


    Using auto-generated normals:


    With good height map data, it looks surprisingly good. I also generate an AO map from the normal as well, since it's just a multiply. I suspect this will be drastically faster than looking up normal map textures on platforms like the quest, which seems to be particularly memory bound.

    Note there is an issue with this technique, which is that the derivatives don't produce the best normals up close- they tend to look "stair step" like:



    This tends to be noticeable when you get close to the textures, or when they have subtle gradient content (like this moss texture does).

    If you get extremely close, in some situations you can see the pixel grid breaking down and moire patterns appearing:

    These could be fixed, but it would require sampling the height maps multiple times and doing a sobel filter, but that would defeat the reason for doing this in the first place by driving the sample count higher. As a cheap, no-texture sample technique, I think this works surprisingly well and is applicable for many games.
     
  23. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    jbooth, release it as an addon! I can guinea pig this!
     
  24. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Nah, made it as part of core..
     
  25. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    Uhhh, what would be the best way for a peasant such as myself to enable this uhhh properly
     
  26. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Wait till my next patch is released.
     
  27. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    This was released this morning.
     
  28. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    Tested it out with URP. Everything is magenta now. I suppose the autonormal feature needs to be adapted for URP as well?
     
  29. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    I wouldn't expect it to need that, but I can check..
     
  30. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Nope, works fine in URP for me.
     
  31. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    Strangely enough after installing the updated microsplat, textures do not appear at all in android builds, and the height normals does not work in urp (with the oculus quest anyways)
     
  32. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    The most recent microsplat has the following error (2019.4.14f, URP, clean project):


    Code (CSharp):
    1. ArgumentException: Could not find MaterialProperty: '_AutoNormalHeightScale', Num properties: 9
    2. UnityEditor.ShaderGUI.FindProperty (System.String propertyName, UnityEditor.MaterialProperty[] properties, System.Boolean propertyIsMandatory) (at <68af50843d0a45398c92799647332ec2>:0)
    3. UnityEditor.ShaderGUI.FindProperty (System.String propertyName, UnityEditor.MaterialProperty[] properties) (at <68af50843d0a45398c92799647332ec2>:0)
    4. MicroSplatShaderGUI.FindProp (System.String name, UnityEditor.MaterialProperty[] props) (at Assets/MicroSplat/Core/Scripts/Editor/MicroSplatShaderGUI.cs:20)
    More importantly, textures no longer appear at all in my Android builds (although they do appear in the editor). I am going to have to revert to an earlier microsplat unfortunately
     
  33. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Works fine for me, in URP, HDRP, and Standard.. Did you try toggling an option on the material's features to regenerate the shader? Or is this after setting it to auto-normals?
     
  34. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    Ok it seems reinstalling microsplat and urp in order seemed to have rescued the android builds issue. The magenta autonormals is triggering a different error (even after exiting bulk shader edit mode)
    Code (CSharp):
    1. Shader error in 'Hidden/MicroSplat/MicroSplat_Base909050615': cannot map expression to ps_4_0 instruction set at line 1657 (on d3d11)
    Leading to this code
    Code (CSharp):
    1.     float3 HeightToNormal(float height, float3 worldPos)
    2.       {
    3.          float3 dx = ddx_fine(worldPos);
    4.          float3 dy = ddy_fine(worldPos);
    5.          float3 crossX = cross(float3(0,1,0), dx);
    6.          float3 crossY = cross(float3(0,1,0), dy);
    7.          float3 d = abs(dot(crossY, dx));
    8.          float3 n = ((((height + ddx(height)) - height) * crossY) + (((height + ddy(height)) - height) * crossX)) * sign(d);
    9.          n.y *= -1.0;
    10.          return normalize((d * float3(0,1,0)) - n).xzy;
    11.       }
    I'm using URP 7.5.2 if that helps...
     
  35. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    try changing that from ddx_fine to ddx and ddy_fine to ddy
     
  36. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    changing them to ddx and ddy respectively gets rid of the magenta effect, although the autonormals do not seem to work (I don't see any normal mapping after making this change).

    Recompiling the shader will undo any manual changes to HeightToNormal it seems.
     
  37. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Yeah, you'd have the change it in the source fragment files in core/scripts/editor/fragments/microsplat_terrain_shared.txt

    There's a strength setting on the effect on the material, you likely just need to turn it up..
     
  38. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    Yep that did the trick! It works now!

    Edit: Slight issue. I noticed the effect is very muted if I set the uv scale of the texture properties to less than 1. Is this intentional? I tend to scale the uvs down for artistic purposes.
     
    Last edited: Jan 20, 2021
  39. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    This is a total hack technique, so it has some funny things about it - since it's based off derivatives, the strength of the effect is related to the texture scale, so you have to increase the strength to counter balance that.
     
  40. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    Ok, it may be necessary to create my own large scale textures to properly take advantage of this new technique!
     
  41. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    1 year later, and I've started to use the ovr metrics tool. It looks like unity terrain is the still the single biggest hit to my game even with extremely low settings. Are there any more recommendations out there to get utp terrain more performance on the oculus quest?
     
    germetic14 and manurocker95 like this.
  42. HIBIKI_entertainment

    HIBIKI_entertainment

    Joined:
    Dec 4, 2018
    Posts:
    595
    Short of converting terrain to mesh and moving any texture/splat) space vegetation over to a mesh, which is another valid and traditional method.

    There hasn't been any more unity terrain system optimisations since (launched) sadly.

    New technologies and ideas about yes, but still very very very experimental, and would be even more so for VR cpu limits

    Providing consistent feedback to Jeremyco and the like can help expedite these sorts of development process and honestly I can only ever recommend providing viable feedback whenever possible.


    I would look on the side at a mesh based solution, if you have an inexpensive method of that right now great, just set up a test scene so to not lose terrain data, splats veggies etc.

    And profile any performance gains.

    The potential downside would be you'd be giving up your microsplat workflow this way, and of course it's a completely different terrain workflow,
    but it's just something you'll have to test for in you specific development environment to judge whether it gives you those gains you, need.

    You are able to turn off terrain draw, shadows ( or not) and keep any space tree or vegetation you may be using on it, and simply replace it with a mesh version of the same terrain too.

    This is probably what I would attempt next if I were in your shoes.
     
  43. germetic14

    germetic14

    Joined:
    Feb 1, 2023
    Posts:
    1
    Have the same problem in 2023 :eek:.

    SImple 130x130 terrain with 3 textures and no vegetations eats -20 fps on Quest 2

    Just can't understand why Unty team can't figure out some solution
    for such popular and important thing like terrain.

    Will try MicroSplat or any alternative.
    If anyone is interested, tag me and I will reply
     
    P_Jong likes this.
  44. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    Yeah you really just have to use a mesh for a terrain, not the unity terrain. I like to make my terrain with unity terrain tools and then convert to mesh, and I like these shaders

    https://assetstore.unity.com/packages/tools/terrain/terrain-to-mesh-195349

    You should see a drastic improvement
     
    P_Jong likes this.
  45. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    5,060
    nilagard and tree_arb like this.