Search Unity

New terrain update custom 'build basemap' shader

Discussion in 'World Building' started by shedworksdigital, Oct 16, 2018.

  1. shedworksdigital

    shedworksdigital

    Joined:
    Nov 7, 2016
    Posts:
    40
    Hello, it was mentioned in the recent terrain update blog post: "you can now override the ‘build basemap’ shader". That sounds really useful to me! Our game has heavily stylised rendering so the standard basemap shader is totally useless to us, but it's being generated anyway. It would be useful to be able to hijack that texture and fill it with pre-computed information that will save me performance in my main shader. Can I get some pointers on how to do this?

    Thanks!
     
  2. zeroyao

    zeroyao

    Unity Technologies

    Joined:
    Mar 28, 2013
    Posts:
    169
    Hey,

    Here is an example of building custom basemaps (from HDRP TerrainLit shader):
    https://github.com/Unity-Technologi...rial/TerrainLit/TerrainLit_Basemap_Gen.shader

    You'll need to write the line
    Code (CSharp):
    1. Dependency "BaseMapGenShader" = "Name/To/Your/Shader"
    in your first pass shader in order for terrain system to pick it up.

    Basically you write several passes for the terrain system to render to a RenderTarget texture. Each pass will generate one such render texture with the name, format and size specified in the pass tags. All the shader properties and keywords are inherited from your template material. Later in your basemap shader you can use these textures with the same names.

    Cheers!
     
  3. shedworksdigital

    shedworksdigital

    Joined:
    Nov 7, 2016
    Posts:
    40
    Thanks, I'll take a look into that. When does the rendering of the base map texture actually happen? I was hoping I could do it in the editor to save myself some overhead but I realise it's probably intended to happen at runtime in case any of the splat data gets changed.

    Also, I notice the TERRAIN_8_LAYERS feature at the top of the file. This is related to the fact that the new shaders don't have an additive pass, right? Does this mean the base map is blending 8 layers in one go, and what will this mean if my custom main shader uses an add pass? I don't think I'm ever going to need more than 8 layers, so it would be helpful to be able to use this feature in my main shader and get rid of my custom add pass altogether. Any suggestions on how to go about doing this?
     
  4. zeroyao

    zeroyao

    Unity Technologies

    Joined:
    Mar 28, 2013
    Posts:
    169
    Yes the basemap texture is generated when either the alphamaps change (via painting) or the terrain layers used by the terrain are changed. However the detection of terrain layer change is only done by the Editor, not in the player. You can call TerrainData.SetBaseMapDirty() to trigger an update manually.

    Also in 2018.3 you can specify any value that is a multiple of 4 to SplatCount tag. That means in each pass - including both first pass and add pass, you can render with more than 1 control map / 4 terrain layers, and TERRAIN_n_LAYERS will be enabled accordingly. That being said, in HDRP the g-buffer format doesn't allow blending so we disabled add passes and extended the number of layers to be sampled and blended to be 8. If you think blending more layers in one go makes sense in your game you can totally do that.
     
    jbooth and shedworksdigital like this.
  5. kite3h

    kite3h

    Joined:
    Aug 27, 2012
    Posts:
    197
    Is there any way to extract the basemap?
     
  6. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Is there any way to handle knowing the terrain topology with this? I suspect your just rendering a quad into a buffer, but if you instead rendered the terrain and had the shader remap it into 0-1 space for the render target, it would open up a massive amount of things you could do. Alternatively, if the height/normal texture you use for instancing were fed to this shader and potentially available in non-instanced rendering mode, then you'd be able to reconstruct that data yourself.

    For instance, some uses I could see in MicroSplat for this are:

    - Generating actual base maps, since triplanar texturing and other world space effects will not work with this right now.
    - Auto baking of procedural texturing, such that the procedural controls bake into splat maps at base map generation time and thus don't have to be run per-pixel. Right now I have functionality to do this, but the user has to manually press a button and change the shader mode to regenerate the shader and disable the runtime calculations. With this, it just becomes a toggle which trades memory for speed.
    - Pre-Pass culling on samples. The basic idea here is like an attribute buffer. When you have an expensive terrain shader which does 32 texture sets, triplanar texturing, and stochastic sampling, a simple implementation might take 500 texture samples per pixel. I currently do a lot of tricks to reduce this down to under 100 potential samples, and use dynamic branching to cull it more. But, on any given pixel there are only a few texture sets really showing at any time - you might have a blend between two of the 32 textures, but only be showing one axis of the triplanar, etc. A shader could be run which renders this into a list of attributes- essentially a fixed size list of float4 values, containing a UV, texture index, and weight for the sample. Then the main shader comes along and just samples and blends these textures, making it a fixed cost without any dynamic branching and much simpler. I suspect somewhere between 8 and 16 texture sets per pixel would cover it.

    Of course, any of these could be done through scripts - but being able to have them all be automatic when users make edits and never make mistakes with any of it would be super cool.
     
    Beauque likes this.