1
\$\begingroup\$

enter image description here

Rimworld (shown above) has many different terrain types.

In order to achieve Rimworld styled terrain, I need to achieve two goals

A) How to render differently textured terrains

B) How to blend these terrains (which is what this question is about)

Demonstrated below as an example ( think each square as different terrain type)

enter image description here

I can easily solve A by rendering a mesh that, say, represent, stone terrain and render another mesh representing grass terrain.

enter image description here

However this is not enough because the sections in which two different terrain types meet must be blended

enter image description here

There are many ways I can think of to achieve this however all methods that I can think of are not fitting to render a giant 2d map (look at the first picture)

\$\endgroup\$
1
\$\begingroup\$

Let's start with some basics: in this case linear interpolation (and its limitations), using pure colours. Once you're on the right track, you can figure things out from there.

First, try to recreate the below image using Mathf.Lerp(), to create a controlled 1D interpolation between two adjacent colours:

enter image description here

(expanded vertically so you can see it more clearly)

enter image description here

Next, try to Lerp() in 2D, also known as bilerp() to create an interpolation on a quadrilateral with 4 colours, one at each of the corners of the quad:

enter image description here

(You can see that bilinear interpolation specifically operates on quads.)

You can see here how the final result comes out between (grid-aligned) world tiles / chunks, with the 2D / bilerped example above, being the middle tile between 4 pure colour tiles:

enter image description here

The easiest way to create the above in Unity is to set up a textured quad facing the camera, then use Texture2D.setPixel() to build a texture according to the numbers you get out of your linear interpolation functions given above.

Once implemented on the CPU using Unity's Lerp() & custom Bilerp(), you can then shift this logic over to lerp() textures correctly on the GPU if desired.

EDIT per comments How your input map must look to be blended this way (grid-aligned cells):

enter image description here

\$\endgroup\$
12
  • \$\begingroup\$ Go through the proper process of learning, and you will save much more time down the line than you would trying to hack your way to a solution (never mind maintaining that solution). You will likely also end up with far better visual results. \$\endgroup\$
    – Engineer
    Sep 1 at 13:37
  • \$\begingroup\$ I'd recommend encoding the colours of just the corners of the grid in the texture's pixels, like a conventional 3D terrain splatmap, and letting the GPU texture sampler's bilinear filtering handle the bilerp for you. That saves texture memory/bandwidth, CPU cycles, and it's less code to write too. 🙂 Then you can use that interpolated splatmap to blend 4 (or even 5) tiling terrain textures in the shader. \$\endgroup\$
    – DMGregory
    Sep 1 at 14:36
  • \$\begingroup\$ @DMGregory Correct - that would be the final goal for the OP, but keeping things simple to start with. A basic understanding of terrain blending is hopefully clear from the above. \$\endgroup\$
    – Engineer
    Sep 1 at 15:19
  • \$\begingroup\$ @Engineer Thanks for the answer. This has a few issues. Approaching this like you do splatmap makes rendering process way too heavy; because there are many terrain types. There could be 10-or more ground(Terrain) types, and I would need to sample 10 times for each pixel to get the right color. Also each terrain type is likely to require a different shader. If I were to render this in a single go, I need a master shader that does a complicated process to render many different effects for each different terrain type. \$\endgroup\$
    – Blue Bug
    Sep 2 at 18:41
  • \$\begingroup\$ I found forum.unity.com/threads/… this, they have splat map with 256 textures... I am wondering how such is possible \$\endgroup\$
    – Blue Bug
    Sep 2 at 20:59
0
\$\begingroup\$

I thought about a solution

enter image description here

If there was a terrain such as above example, dirt should be below grass.

I could render dirt terrain to overlap grass terrains a little (below)

enter image description here

Then render Grass mesh on top of dirt terrain, then have its edges be rendered with transparency

enter image description here

However I still need to solve needing to apply different transparent value at the edges.

I wonder if I were to select this method, should each vertices contain "transparency value"? so that vertex at the edge contains zero-or-low transparency value

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.