Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question How to represent (draw and use) 2d grid array "smoothly"? (discrete data as continuous)

Discussion in '2D' started by unity_3KoGAU6lZHRhFA, Feb 11, 2023.

  1. unity_3KoGAU6lZHRhFA

    unity_3KoGAU6lZHRhFA

    Joined:
    Jul 26, 2022
    Posts:
    7
    Almost all of my 2d game ideas require solving this kind of situation:
    i have a complex procedural map generation that needs to be stored in memory as a 2d data (2d grid array obviously).
    This map doesn't have a lot of details so i can use not too big of an array, and therefore less memory, right?
    it's just lakes, rivers, simple landscape slopes and so on.
    it needs to be just a 2d background.
    And here comes the problem. Any kind of visualization i used to use, results in a very AWFUL Griddy-looking image. This is NOT a tile map, it needs to be smooth, and yet there's no reason for me to use 100 times more memory for higher resolution! It's a very simple data that just needs to look smooth.
    I need a "grid data interpolation" sort of thing. i googled "Unity visualize 2d array smoothly", "unity how to draw a grid smoothly", "unity how to draw a grid in non-pixelated way" etc with no avail.

    it might have a lot to do with shaders, but for some reason i haven't seen a single code snippet of (probably)fragment shader code that could do something like that. i need practical answer and not "go and learn blabla".

    This issue has 2 major intrinsic questions:
    * How to draw the raw 2d float data smoothly (2d interpolation)
    * If i choose a random point float X and float Y on the map, how am i supposed to get that interpolated value from code? (interpolated height for example)
    code sketch:


    Code (CSharp):
    1. float[][] map;
    2.  
    3. //should return the interpolated height for the given position
    4. float GetLandscapeHeight(Vector2 worldPosition) {
    5.         ????  //this should not behave like a tile grid
    6.               //it has to be smooth!
    7. }
    To visualize the problem:
    (this image is not the ideal reference, it's just an intuitive simplified sketch i made for this question)

    Screenshot 2023-02-11 23-06-11 (2).png

    Here, yellow gameObject should know that it stays in the red area.
    And now extrapolate this binary example to the spectrum of heights given by the height map. The height should change very smoothly, not like stairs nor polygons.

    and obviously, the performance is a big question too. this generated map is gonna be used a lot by lots of game objects in the scene.

    Yes, i can just experiment with random shaders and scripts and end up getting something meaningful, but i'm asking this question to get more in-depth comprehensive answer from experienced people! and to help others if they need a similar thing even if it's not specifically about landscape heights. Thank you in advance! and i apologize for taking your time.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,960
  3. unity_3KoGAU6lZHRhFA

    unity_3KoGAU6lZHRhFA

    Joined:
    Jul 26, 2022
    Posts:
    7
    Kurt-Dekker, this is definitely a valuable answer for other people who ended up in this thread. Thank you! this answer more or less matches the simplified illustration given above. my simplified illustration presented a single binary border between red and white areas, and marching squares are a really good choice for that. As far as i see, "marching squares" technique is good for generating a mesh. useful to know! your answer is undoubtedly valuable.
    it's all about generating a mesh or mesh-like structure. In 2d, from this, i can easily see how i can create a map that looks like in this tutorial: https://catlikecoding.com/unity/tutorials/marching-squares/

    Moving on:
    But googling the usage for marching squares, i don't think it's a comprehensive answer nor the direct answer for my situation. apparently, my question is much more than that single link. As i initially said, it's a 2d float array height map that needs to look smooth in a 2d world.

    For clarification, let's draw a second, non-simplified illustration to show what is a height map:
    questionHeightMap.png

    i sincerely apologize for my awful-looking art, but it shows a map with diverse heights at different points on the map. white is a mountain. darker = lower. based on water level, we should consider everything near-black as water that surrounds the island.

    And here comes the problem. For my game, this kind of map needs to be like a background 2d world and you can move in this world, but.... :

    Screenshot 2023-02-12 18-58-27 (2).png

    this is the highest trillinear filtering and yet pixels are not interpolated enough to look as a natural landscape! Regardless of how much resolution i have, at a certain scale i will always see these garbage pixels!

    Here is the point filtering:

    Screenshot 2023-02-12 19-26-00 (2).png

    All transitions should both, look and behave smoothly. not like stairs. so repeating the words of the title - represent discrete data as continuous.

    Screenshot 2023-02-12 20-11-06 (2).png

    here, drawn lines are just for illustration. it should be visualized "infinitely" smooth from the shore to the hill for example. and it's not a 3d terrain, it's just like a background image depicting 2d world.

    i haven't been able to find marching squares as a full-fledged solution to my problem, because generating a mesh is not my purpose. maybe i'm mistaken, i wanna know. and if i am, then i wanna know how to approach these marching squares if they are actually the answer for my case scenario. there's just very little information with detailed explanation of possibilities around this topic and it's very easy to get confused.

    i've spent more than 3 hours writing this second question, trying to find proper words and images, and i really hope there will be somebody who is able to spend at least 15 minutes to elaborate and give a practical approach maybe with a certain code snippet. Thank you!
     
  4. huttarl

    huttarl

    Joined:
    Feb 14, 2023
    Posts:
    2
    I'm fairly new to Unity, so I may not be able to help much with implementation. But it sounds like what you're looking for is https://en.wikipedia.org/wiki/Multivariate_interpolation#Regular_grid
    For example, you might be able to bicubic interpolation between your data points. (Bilinear interp is easier but probably wouldn't look as smooth as what you're looking for.)

    So for your first "intrinsic question," namely to display the smooth terrain based on the grid of data points without generating and storing an interpolated mesh, you probably do need a shader, which uses bicubic .

    For the second question, it sounds like you need to define a function f(x, y) that finds the right cell in your data grid, performs the interpolation based on the nearest 4x4 data points, and returns the value. See https://en.wikipedia.org/wiki/Bicubic_interpolation and https://web.archive.org/web/2005102...a.psu.edu/sites/geocomp99/Gc99/082/gc_082.htm
     
  5. huttarl

    huttarl

    Joined:
    Feb 14, 2023
    Posts:
    2
    P.S. One way to achieve a continuous surface at any scale that looks fairly organic is using Perlin noise (https://mzucker.github.io/html/perlin-noise-math-faq.html). For Perlin noise, your data points would be unit vectors. I'm not sure how you would set those if your map generation is non-random though.
     
  6. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,022