Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Grab and resize a terrain Heightmap texture?

Discussion in 'General Graphics' started by protopop, Nov 29, 2019.

  1. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    heightmaps.png

    I'm trying to think of a simple way to recognize features as my player crosses terrain - most importantly lakes. As a human I can easily recognize lakes on the first Heightmap.and if I resize it I could see the major features in a way code could use it.

    get TerrainData.heightmapTexture
    change the resulting render texture height and width to 4x4 which im guessing would interpolate the Heightmap values like above?

    Then I could just map player x and z to a position on the 4x4 image and see what kind of future they are standing near. Lakes would be dark and mountain tops high.

    This would also allow me to just see the larger terrain features because it would have to be a big lake to darker a pixel in an 8x8 or 4x4 image

    Or maybe it is more efficient to use TerrainData.GetHeights and somehow shrink that array x and y?

    Is this a good approach?
     
  2. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    OK Im partway there. BTW if I answer my own questions I like to write it down because sometimes even years later I'm looking for a solution to something I solved and I find my own posts:)

    Anyways I tried a few things

    GetHeights
    This was fast but hard to use the float data

    Texture2d
    Was slow

    I ended up using the terrain Heightmap render texture. You can't resize a render texture so I blitted it t a smaller one and used post filtering to make sure it stayed pixel, although at 8x8 size maybe I don't need to set that.

    I end up with a small render texture very quickly where I can see the main geographic features.

    Now I need to map my players position on the Heightmap to this mini map so I can tell when the player is on a certain type of landscape.

    blits.png

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TerrainScanner : MonoBehaviour
    6. {
    7.     public Terrain myTerrain;
    8.     public TerrainData tData;
    9.     public RenderTexture hTexture;
    10.     public RenderTexture newTexture;
    11.     public int size = 4;
    12.  
    13.     void OnEnable()
    14.     {
    15.         if (myTerrain == null) { myTerrain = Terrain.activeTerrain; }
    16.         tData = myTerrain.terrainData;
    17.         hTexture = tData.heightmapTexture;
    18.         newTexture = new RenderTexture(size, size, 24);
    19.         newTexture.filterMode = FilterMode.Point;
    20.         Graphics.Blit(hTexture, newTexture);
    21.     }
    22. }
    23.  
     
    Last edited: Nov 29, 2019
  3. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,492
    Rendertexture, generate mipmap, sample lower mip?
     
    protopop likes this.
  4. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    I ended up blurring the rendertexture to a smaller rendertexture and it worked . I can detect lakes in general but I want more resolution so i am going to try blob recognition. I’m just learning all of this as I go along so I’m not sure but so far it’s on the way and seminworkikg pretty well. I set a beacon where a lake is, a gameobjectbthat checks every X seconds how far the player is and writes to the screen the name of that particular lake which is itself procedurally generated
     
  5. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    I actually thought about grabbing the mip map but I couldn’t figure it out but the blit works well
     
  6. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    Screen Shot 2019-11-29 at 3.39.37 PM.png

    The blue pillars represent lake areas. Im kind of trying to figure out though how you group lakes really. because is this one large lake or several smaller ones. Thats more of a philosophical issue but im still not sure how to group pillars together so that I could create one centre beacon that contains the information about that particular lake. But it works well enough for the moment as a simple example.
     
  7. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,492
    The first instinct would be to group area into convex zones, then have a minimal size for lake, and minimal size for "door", that is, if a zones is smaller than a lake, but bigger than a "door", it get captured by a connected zones, then once the composite are done, composite that connect to each other qualify as a lake, smaller zone get to be "pass" between too lake.
     
    protopop likes this.
  8. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    Yeah I am kind of thinking that too. Those blue pillars act like beacons notifying you when you’re close that you’re near a lake but it’s too imprecise.

    I already figured out how to make a low resolution version of the heightmap for fast processing so I think I should use that. Maybe like 64x64 version

    But I have to figure out how to posterize or filter that so the convex low area stand out and group into blobs

    Maybe just doing a high contrast effect on it and keeping all the dark spots below a certain height as lakes. High contrast could also separate the blobs.

    I’m going to try and figure out how to run a high contrast filter on a render texture, or maybe how to convert a render texture to a texture 2d, but since I already have a render texture I would rather save on processing