Search Unity

[FREE]MicroSplat, a modular terrain shading system for Unity Terrains

Discussion in 'Assets and Asset Store' started by jbooth, Aug 9, 2017.

Thread Status:
Not open for further replies.
  1. punk

    punk

    Joined:
    Jun 28, 2013
    Posts:
    408
    Yeah cool, I've got both now so I'll have a play and see what suits what I'm sure I'll have lots of uses for both ;) thanks again for making such great tools
     
  2. punk

    punk

    Joined:
    Jun 28, 2013
    Posts:
    408
    turns out megaSplat is a really good fit for my larger buildings some of them are huge I've got one that's about 1km high, so the large number of textures is perfect.

    sticking with microSplat for my terrains and walkable areas I'm just loving the simplicity of it, I'd definitely be interested in raindrops on the wetness/streams/lava module it would be a really useful feature for me

    I've also noticed that with the blending module if you have snow it still blends with the texture underneath, I was thinking of using it for snowdrift, would it be hard to make it blend with snow when there is snow?
     
  3. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Oh, nice find - fixed, will be in the next update.
     
    punk and ZoneOfTanks like this.
  4. eXonius

    eXonius

    Joined:
    Feb 2, 2016
    Posts:
    207
    I've tried out Microsplat and it seems quite nice so far.

    But how do I add (and remove) textures to my MicroSplat material during runtime? My game creates all terrain during runtime (standalone) and edits the splatmaps using scripts.
     
  5. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Do you generate the texture data itself? Or just the choice of textures? If you really need to generate textures, you'd have to use Graphics.CopyTexture to copy them into a Texture Array the same way the texture packing code does, and pack data into the correct channels (ie: Diffuse + Height in the alpha for one array, Smoothness/NormalR/AO/NormalG in the other array).
     
    eXonius likes this.
  6. eXonius

    eXonius

    Joined:
    Feb 2, 2016
    Posts:
    207
    It's basically a map editor. But the thing is the user can choose up to 16 textures from maybe 30 different textures and add/remove them at will.

    Thanks for the fast response by the way!
     
  7. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    If your comfortable with shaders, you could pack all the textures into one array, then change the shader to look up which textures the user has selected from an array. Wouldn’t be hard to add, but not something I’d want in the main branch.
     
    eXonius likes this.
  8. eXonius

    eXonius

    Joined:
    Feb 2, 2016
    Posts:
    207
    Thanks for the suggestion. But wouldn't putting all textures in a shader array waste video memory? Some of the textures might never be displayed and replacing one of the active textures doesn't need to be very fast so just a way to reassign the texture array similar to the way it's done in the editor now would probably fine.

    I don't have a problem with modifying code, just looking for hints on the easiest way to do it. Preferably without changing the shader.
     
  9. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    It'll waste some video memory if they are never used, but it won't be accessed, so that's not the worse thing in the world. Constructing your own arrays at load time is reasonably straight forward as well, but you'll need to pack them into the right formats and compress them before hand so you can copy them right to the video memory and not end up with duplicate versions on the CPU. Anyway, you can find examples of all the code you need in the TextureArrayConfig files..
     
    eXonius likes this.
  10. eXonius

    eXonius

    Joined:
    Feb 2, 2016
    Posts:
    207
    I'll check those scripts out, thanks again!
     
    jbooth likes this.
  11. superkratos

    superkratos

    Joined:
    Sep 4, 2017
    Posts:
    112
    Here's the steps I was following trying to paint blend Area by hand, Mr Booth. Please check to see if you understand my problem..
    upload_2017-9-29_16-22-54.png
    upload_2017-9-29_16-23-11.png
     
  12. superkratos

    superkratos

    Joined:
    Sep 4, 2017
    Posts:
    112
    It doesn't reveal the original material I painted, and the blend edge is weird.
     
  13. superkratos

    superkratos

    Joined:
    Sep 4, 2017
    Posts:
    112
    I have prepocessed the mesh, by the way.
     
  14. superkratos

    superkratos

    Joined:
    Sep 4, 2017
    Posts:
    112
    What I wanted was something like this:
    upload_2017-9-29_16-33-27.png
     
  15. superkratos

    superkratos

    Joined:
    Sep 4, 2017
    Posts:
    112
    Because VTP only supports 3 materials on a mesh and MegaSplat supports much more, so I wanted to give it a try..
     
  16. sylon

    sylon

    Joined:
    Mar 5, 2017
    Posts:
    246
    Hi.
    Follow up on my frame rate issue on Android.
    I have been testing and testing, but for some reason, since v1.2, i am getting great framerates!
    50-60 fps with heightblending on.
    6 textures so far, k512, per texture brightness, uv's and interpolation contrast.
    (fastest blend, simplified lighting)
    I had some small ideas to maybe speed things up a bit more, but it's just not needed.
    Good times :)

    I was thinking about using meshes with Megasplat for my terrains, but these results make me wonder if a combination with MicroSplat and the upcoming Vegetation studio and Terrafirma wouldn't better fit my needs.

    So i am considering trying a few more MicroSplat modules and i have a question about that.
    Will for instance the lava/stream module work on a lightmapped terrain (non-directional)?
    I realize these extra features will cost me performance, but is there a way to disable a feature in realtime? So it will only impact performance when needed?
     
  17. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Ah, I see- so the problem is that both MegaSplat and MicroSplat are using the same data. Color.A is used by MegaSplat to control which texture is on the bottom layer, and it's used by MicroSplat to control the alpha of the blend. So when you paint all one color in there, you are also painting which texture index the bottom layer uses.

    Some possible ways around it:
    - Use a two layer shader in MegaSplat and paint on the second layer only
    - Just use MicroSplat- set the blend distance really high and paint over your object by painting on the terrain under it
     
  18. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    MicroSplat is usually faster than MegaSplat, and MicroSplat is going to work fine with TerraFirma (most like already does, but will be made to work well with it either way). So it's likely the best combo once all of that is in place.

    The lava and streams should work fine with a light mapped terrain - everything is done in a surface shader, so there's no specific light mapping code in MicroSplat. The actual water and lava effects can be turned on/off my making an alternate version of the shader and swapping to it when needed; though I personally prefer to leave those things on as your only as good as your worst FPS anyway (though on mobile, power savings is always good). The real-time simulation can also be easily disabled by disabling the component which updates the simulation.
     
    ZoneOfTanks likes this.
  19. txarly

    txarly

    Joined:
    Apr 27, 2016
    Posts:
    197
    Does microsplat work with Terrain Composer 2?in this case, what is the way to do it?thanks
     
  20. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    It’s free to download the core module, so it should be easy to test. MicroSplat uses the Unity Terrain format, so it should work with the data TC2 outputs.
     
  21. coverpage

    coverpage

    Joined:
    Mar 3, 2016
    Posts:
    385
    Microsplat
    screen_1920x1080_2017-09-30_10-54-47.png screen_1920x1080_2017-09-30_11-06-45.png
     
    jbooth likes this.
  22. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Ok, this only happens when per-texture UVs are turned on. I have a fix implemented for MicroSplat and will be doing one for MegaSplat as well. The reason is rather interesting if you're into GPU tech- but non-trivial to debug and fix for sure. Details below if anyone cares:

    Basically, when a GPU works on pixels, it does them in 2x2 blocks on the screen. When a pixel goes to sample a texture, it fetches all the data needed for that 2x2 block and effectively shares it with the other 3 pixels, saving them from having to look up the data as well. There is an assumption here that these pixels are doing the same work, and in most cases, this is correct. However, many things can break this parallelism - for instance, if there is a triangle edge crossing that 2x2 block, then it can't share that data anymore, because it's UVs and such might be completely different. (This is one reason very small micro-triangles are bad- lots of edges reduces shading rate). Usually this is all handled by the GPU - you write code, it figures out where the parallelism needs to be broken and just handles it.

    Internally when a GPU goes to sample a texture, it figures out how far those other 3 pixels are away from itself in screen space (these vectors are what's called screen space derivatives). It then uses this to determine which mip map to look into, such that the pixels 1 screen pixel away are also 1 pixel away in the texture's mip. It then fetches the values and everyone gets the data with less work.

    So, what was happening in this case? Lets say our first pixel is going to sample textures 1 and 3 from the array, and blend them with weights (0.6, 0.4). And lets say texture 1 has a UV scale of 1, but texture 3 has a UV scale of 1.5. Now, on the very next pixel, in the same quad, the weights of the textures are reversed- this reorders the indices so now we have weights (0.6, 0.4) but with texture index 3 and 1 (swapped). The UV scale is also swapped with the textures. Normally for this to happen, the GPU would have a triangle edge to break up the quad's shading, and it would all be fine- but this is all happening inside the pixel shader itself, which is quite unusual.

    So now when that first pixel fetches the texture data, it says "My neighbor is this far away, based on my UVs". But because the other pixel uses different UVs, the data it gets back is not from the correct mip map, and is thus the wrong pixel. Further, because the texture indexes have swapped, it ends up grabbing the wrong textures pixel. So for an area of exactly one screen pixel, we end up sampling the wrong texture with the wrong derivatives.

    The fix for this was to make all pixels in a quad have the same derivatives, regardless of their UV coordinates. The traditional way to do this is to compute the derivatives yourself and pass them into the samplers. But since the GPU doesn't know if you're going to pass each pixel the same value, what it does is make every pixel do the full work. This reduces shading rate by a factor of 4, which makes it extremely expensive to do this because you are getting none of the sharing. So I wanted to avoid using the gradient samplers, and had actually removed their use in MegaSplat recently for a massive speed boost, but noticed this issue cropping up. And by massive speed booth, I mean going from ~33fps to 47fps on a stress test scene- the kind of gains that are usually very hard to get.

    So rather than using the gradient samplers, what I do is compute the mip map to be used for all pixels in the quad explicitly - I average the UV scales which are going to be applied to all UV coordinates, and compute the mip map to be used from that UV * averageScale. This allows all pixels in the quad to share the sample and thus doesn't affect shading rate (well, some slight ALU is used for the mip calculation, but nothing major).

    This does have a slight downside- if you scale your UVs by wildly different amounts, the MipMap used in each texture sample will be based on the average UV scale. So if 3 of the active UV scales are at 1, and only one is at 100, it will bias the mip map for all the textures to be blurrier since the average is now a UV scale which is 25 times the original size. However, within small scale ranges (like 50% to 200%), it's pretty hard to tell, so this seems like a decent way to fix the issue. And preferably, no one should have wildly different UV scale ranges anyway, or you'll have very inconsistent texel size, which looks bad too.

    Anyway, that's the deal - I'll be looking to get this patches into MegaSplat and out for both systems soon.
     
    Akshara, teutonicus, frosted and 6 others like this.
  23. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    That's really impressive. How'd you figure this out?
     
  24. coverpage

    coverpage

    Joined:
    Mar 3, 2016
    Posts:
    385
    It does.
     
  25. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Years of experience, really; there's not any particular debugging technique or tech available to help with this kind of stuff, you just have to think through how the low level hardware works and try to figure out what assumptions you or it is making which is incorrect. Everything is basically optimizations fighting against each other; the core technique used in MicroSplat which makes it fast is about limiting how many samples the GPU has to make, and it was fighting against a core technique that GPUs use to speed up texture access when per-texture UVs were enabled. The trick is in figuring out how to have both optimizations instead of one or the other..
     
    eXonius and frosted like this.
  26. eXonius

    eXonius

    Joined:
    Feb 2, 2016
    Posts:
    207
    I managed to edit the scripts so that I can add and remove textures at runtime in standalone and it seems to work well. Now I just need to figure out how to change the normal and smoothness strength programatically too.

    But there's one more thing I'll have to solve, I get these visible texture seams between my tiled terrains:



    When I used the default terrain shader I managed to make my terrains seamless by replacing the textures UV scaling with a global UV scale in the shader. However by doing this change I also lost the ability to set individual UV scales for each texture.

    Is there any way to have seamless UVs between terrains while still being able to change the scale of the UVs for each texture?
     
  27. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    If you are using the UVs, then they will only line up if they are multiples of the original UVs. The other option is to use world space UVs instead of the ones on the mesh; there’s not an option for this right now, but it would be very easy to add.
     
    eXonius likes this.
  28. punk

    punk

    Joined:
    Jun 28, 2013
    Posts:
    408
    Hey bro, just trying out the puddles feature pretty nice, is there a way to darken the puddles or tint them if you want them muddy? I'm just using the puddle feature on its own
     
  29. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    There's not a tint, but you can get a more muddly look by adjusting the global porosity.
     
  30. punk

    punk

    Joined:
    Jun 28, 2013
    Posts:
    408
    ah thanks yeah I see in working in the demo now, must be something to do with my maps
     
  31. punk

    punk

    Joined:
    Jun 28, 2013
    Posts:
    408
    that is marvelous!
     
  32. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Added an option for worldspace UVs tonight, so you'll be all set in the next update..
     
    eXonius likes this.
  33. eXonius

    eXonius

    Joined:
    Feb 2, 2016
    Posts:
    207
    Awesome, thanks!
     
  34. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    1.3 was submitted last night:
    • Added option to select which textures use triplaner and which use standard UVs via a per-texture property
    • Added an option for height based blending in triplanar texture resolve. This can greatly improve the quality of triplanar blending for a small cost.
    • Added an option for WorldSpace UV coordinates for the splat textures
    • Fixed bug causing small dots to appear between textures when per-texture UV scale is enabled.
    • Work around for startup race condition crash in Unity 2017’s terrain code.
    • Fixed an issue with Terrain Blending module where terrain blended meshes would not blend with snow
    As usual, you should wait until the UAS released all the module updates before upgrading.
     
    DonLoquacious, eXonius and punk like this.
  35. gecko

    gecko

    Joined:
    Aug 10, 2006
    Posts:
    2,241
    It just keeps getting better and better!
     
  36. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Doh, I missed a change in the tessellation module- I've submitted a patch for just this module, but if you get a compile error when turning on tessellation, go into microsplat_tess_func.txt and change line 48 to:

    Code (CSharp):
    1. Setup(weights, i.texcoord.xy, config, w0, w1, w2, w3, worldPos);
    Hopefully the asset store will get it through quickly, sorry about that!
     
  37. wmpunk

    wmpunk

    Joined:
    Sep 5, 2015
    Posts:
    71
    Hello mr. Booth, I have problem I was hoping you could help me solve.

    I need to insert a texture sample before the Setup function through a custom FeatureDescriptor subclass. Originally I just inserted the sample inside of the Setup function through the WriteFunctions method of the FeatureDescriptor. This worked fine but broke the shader when tessellation was turned on. I went back through the shader code and realized I needed to put the sample call inside SurfImpl and disp to work correctly. Unfortunately I can't seem modify the shader through FeatureDescriptor methods that far down as the WriteFunctions string builder only goes down to UnpackNormal2.

    Is there something I'm missing or is there currently a way to do this with FeatureDescriptor methods? If not would it be possible in the next update to add some sort of Finalize method that passes a string builder of the complete shader before compile for modifications that could only be done with the complete code?
     
  38. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    So why not just modify the source fragment files directly? Or are you trying to make your changes fit within the framework as a new module so you can merge in updates more easily? The module system isn't really designed to be 100% extensible without modifying the core files; that would have been overkill for my needs, and made the framework much more complex, having to handle ordering between the modules, etc. So those APIs may change, and the main fragment files usually change with every major point release (1.1 is change of API between core and a module, 1.11 is not).
     
  39. wmpunk

    wmpunk

    Joined:
    Sep 5, 2015
    Posts:
    71
    I had a feature idea and decided to try implementing it myself, it worked out so well I decided to try making a complete module out of it. I was hoping to stick within the framework so that base scripts could just be added in the assets folder and you would just enable the feature like the other modules.
    I made a custom FeatureDescriptor thinking I could get the full code through one of the string builders, I'll just have to work around that then.

    Aside from getting it properly compiled through the MaterialEditor, it's almost ready to show off and alpha test. Obviously your first on the list to check it out. haha
     
  40. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Hey, if it's interesting and useful to everyone, we could add it to the main package.

    Note that you don't really have to add the code through the module. You can use the module to turn on/off the feature via the defines, and show the correct GUI or add per texture properties. The code itself can just be in the shader with #if's around it.
     
  41. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,561
    It looks wonderful. Anything hat makes good things simpler is great.

    I'm a mobile developer and I'm wondering if it works on IOS and Android?
     
  42. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Yes, on Metal or OpenGLES 3.0.
     
    eXonius, DonLoquacious and protopop like this.
  43. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,561
    Thank you:) I was so into the description i didnt even realize the core was free - ill test it out - thanks for the prompt reply and keep up the impressive work.
     
    jbooth likes this.
  44. Zenchuck

    Zenchuck

    Joined:
    Jun 2, 2010
    Posts:
    297
    "Shader error in 'MicroSplat/Terrain': too few parameters in function call at line 440 (on d3d9)"

    440 Setup(weights, i.texcoord.xy, config, w0, w1, w2, w3);

    Tesselated mesh appears white.

    Unity 5.6.1
     
    Last edited: Oct 4, 2017
  45. debuk

    debuk

    Joined:
    Sep 5, 2017
    Posts:
    1
    See post #386
     
    Zenchuck, eXonius and jbooth like this.
  46. magique

    magique

    Joined:
    May 2, 2014
    Posts:
    4,030
    Did I miss something? I thought Microsplat didn't work with mesh terrains. Has that been added? Or does Terrafirma just work more like standard Unity terrain so the shader is compatible somehow?
     
  47. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    The later; Unity Terrains are just meshes; what MicroSplat takes advantage of is things like the terrain being able to be represented as a height field and having unique/continuous UVs which clearly map to a texture. With raw meshes, none of that is necessarily true.
     
  48. gecko

    gecko

    Joined:
    Aug 10, 2006
    Posts:
    2,241
    I would love to see a new MicroSplat module for snow trails -- with different styles, like smooth grooves for skis, rough trenches for feet, etc. Any chance of that?
     
  49. superkratos

    superkratos

    Joined:
    Sep 4, 2017
    Posts:
    112
    Hi, Mr Booth! I've got this error when I import the stream&lava module..Do you have any idea what's wrong with that ?
    upload_2017-10-9_15-26-34.png
     
  50. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Sounds like you have two copies of the streams module in your folder structure.
     
Thread Status:
Not open for further replies.