Skip to content

Quick Start Guide

mohsenph69 edited this page May 23, 2024 · 1 revision

This page is possible thanks to the significant contributions of rossunger

Quick Start Guide

  1. Install and activate plugin
  2. Create new 3D scene. Add an MTerrain node. Select the node and look at the inspector for the next steps.
  3. Set a path to the Data Folder. This should be an empty folder where MTerrain will save all the terrain data.
  4. Set terrain_material to an MTerrainMaterial. As you set a new material with new shader, a basic shader for Terrain will be created!
  5. Choose region_size and min_size. These are the most important settings, min_size define the grid units, and you cannot change later. To make good choices it is helpful to understand what regions and chunks are. you can also read this page for more information!

min_size defines the smallest possible grid unit in meters. Basically terrain divided into smaller pieces! this define the smallest piece for terrain! this cause some of the pieces of Terrain will be culled and not shown!

camera_frustum_s

Something like image above! but this is not the end of story, further away chunks get merged for this take a look at base concept page!

region_size defines how big each region will be. This setting is in grid units. min_size * region_size = region size in meters.

What region size should I choose:

That depend on various thing! One can be how much further away your player is able to see! If you plan that your player be able to see a very vast landscape choose a bigger region size! (You can define up to how many region around player should be loaded by setting region limit) imagine you have a terrain which you want that player can see up to 8km far away! in that case if your region size is 1km, a grid of 8X8 region should be loaded at each time! which means 64 regions are loaded at each time! Now if you want to make the same terrain with 512m region size! 16X16 grid of regions should be loaded at each time! this means 256 regions should be loaded at each time! This can be more heavy to process! some of the problem which a small region size create in this case is:

  • It won't let the terrain chunk to be merged! Basically each terrain chunk will be merge further away but it can not go beyond the regions! take a look at the base concept page!
  • each region create a separate material which means less performance! These are some disadvantage of smaller region size but smaller regions size can also have some advantage which are:
  • If you plan to modify terrain in run-time smaller region size has much better performance!
  • smaller region size means less VRAM memory! basically each heightmap in each region get resized based on how much further away they are from camera! and smaller region size perform better for VRAM usage!
  • As you through terrain smaller region size load faster!

At last I can say you don't need a terrain which player can see up to 8km, try to make a terrain which player can not see too much far like 2km away! and then try to use smaller region size like 512m, If you plan to make light game, maybe that work on android or ... go less than that! maybe 1km and each region 256m


e.g. if you want a terrain that is 8192x8192km, and you want to divide that into 16 x 16 regions for a total of 256 regions, you could try the following settings (Please note region_size and terrain size are in grid-unit):

option a) min_size(grid unit) -> 64! which makes each region to be 8 grid unit -> 8 * 64 = 512x512m, and use a terrain size of 128 * 64 = 8192

option b) min_size(grid unit) -> 32! which makes each region to be 16 grid unit -> 16 * 32 = 512x512m and use a terrain size of 256 * 32 = 8192

Formulas:

sqrt(Terrain size in meters) = min_size * terrain_size
sqrt(Region size in meters) = min_size * region size
sqrt(Number of regions) = sqrt(terrain_size in meters) / sqrt(region_size in meters)

NOTE: once you've started sculpting your terrain you cannot change these settings.

  1. Choose other settings:
  • a) terrain_size x min_size = Terrain size in meters. e.g. if you want a 8192x8192m terrain, and your min_size is 64, you should make your terrain size be 8192/64, which is 128. Increase this number to add more regions
  • b) region_limit controls how many regions can be loaded at one time. lower this number for faster load times.
  • c) layers_data_dir is a path to a folder where MTerrain can store layer data. This is needed if you intend to use layers for non-destructive terrain sculpting.
  1. Press Create in the inspector to see your terrain.
  2. Press the Paint button in the toolbar (include pic) to start sculpting your terrain. Switch to the Paint tab that appears in the top right dock (image). Select a brush, brush size, and brush mode. You can now sculpt your terrain. You can use Layers for non-destructive editing.

NOTE: Remember to save regularly - the painted data isn't automatically saved. You can do this by saving the scene

Importing Heightmap

  1. Go to Project -> Tools -> Import MTerrain data
  2. Select the file to import.
  3. Set region_size.(Please note this region_size is in px) This controls how your heightmap will be divided into regions. e.g if your heightmap is 512pxx512px, and you choose 256, then your heightmap will be divided into 2x2 regions of 256x256 squares. NOTE: there is no way to scale your heightmap in the xz plane during this import process
  4. Toggle the "heightmap" button
  5. Set the height scale for the import. ?????
  6. Choose the output directory. This should be the same as your DATA folder for your MTerrain node.
  7. Import. This can take some time and your computer may become unresponsive. When complete you should have .res files in your DATA folder.

NOTE: the regions size should be match the regions size in your terrain setting, you can check everythign by selecting terrain and pressing the info button!

Importing Heightmap in Tile mode

You can divide your height-map into different pieces and then import them into terrain, in that case each piece resolution should match your region size in pixel! This is good for importing very large terrain as the first method does not work with very large terrain! As you select your Heightmap piece if its name has this pattern [name]_x[number]_y[number].[file extension] it will automatically detected as the tiled Heightmap.

MGrass Quick Start Guide

  1. Setup an MTerrain
  2. Add an MGrass node as child of MTerrain
  3. Create MGrassData and save it as a .res resource
  4. Select density for this MGrass. This controls how small the smallest grid square of grass will be.

IMPORTANT: You can not change this setting after you start painting grass.

E.g. for grass 1.0 or 0.5 density is good. For trees, 16 or 8 density is good. Play around with the other settings, paint some mgrass and decide if you need to start again.

The bigger the density the bigger the gird cell of grass, this make your grass faster and more importantly it make the grass save file smaller! the only downside of bigger density is that you can not put accurately grass on terrain!

  1. Add a Mesh for Different LODs. You can put two same mesh in two LOD, for example if you put mesh001 to LOD0 and LOD1, as LOD change from 0 to one, the mesh will not change! this is up to you to decide how you want to handle LOD level! if you don't set a mesh LOD it will be removed completely and this is a good way to ingnore grass far away! for example if you don't need grass with lod5 and beyond don't set any mesh to them!
  2. Add a Material. Different LOD are optional. You cannot have more than one material per mesh
  3. Add grass_lod_settings. Here you can control the quantity of grass inside each cell, random rotation, scale, position.

The quantity of grass is controlled by "grass_in_cell", As we told before grass is divided into a grid, which the size of each cell is determine by density which we set in grass data resource! "grass_in_cell" control how many grass should be inside each cell!

  1. After setting grass data and meshes, you need to restart terrain so grass will be initialized for first time! Click on MGrass node and in press the paint button in the toolbar (include picture). Click the Paint tab that appears in the inspector dock. Select a brush size, and a brush (null is just a round brush). Now you can paint your grass on the terrain.

Regions, Chunk, and Grid units

To work with MTerrain it is helpful to understand what Regions, Chunk, and Grid units are.

If you zoom out all the way, you have a terrain. This terrain is broken down into regions. Regions are like stand-alone mini-terrains that have been stitched at the edges. MTerrain loads and unloads regions in their entirety. You cannot load part of a region only.

If you zoom into a region, this is where the efficiency magic happens. MTerrain breaks a region into chunks, and does some magic to make chunks that are far away use less resources for rendering.

The smallest possible chunk is called a grid unit. Most of the settings are measured in grid units

Troubleshooting:

  1. I'm painting but my grass isn't showing up. Why? Firstly, select MTerrain and toggled Create on and off again. Some setting in MGrass require you to recreate the terrain to appear

Another issue might be that your density * grass_in_cell is lower than the size of your brush. Try increasing grass_in_cell or using a bigger brush

Another issues could be that you've accidentally deselected the MGrass node. Try turning paint mode of and on again.

  1. I'm sculpting the terrain, but my work is disapearing. MTerrain doesn't auto save you sculpt data. If you move in the viewport and MTerrain loads a different region before you've saved, the data for the unloaded region will be lost.

FEATURE REQUESTS

  1. A tool to rescale the current heightmap data, both in XZ plane and in the Y direction.
  2. Autosave when painting. or at least warn when an unsaved region is being unloaded? or autosave when unloading a region
  3. A calculator for deciding region size and terrain size. The MTerrainInfo tool seems like a good place for this
  4. Ability to export entire heightmap as a single exr file
  5. a button to recreate terrain that's clickable when an MGrass node is selected.
  6. An option to keep terrain on when switching scene, or at least an option to automatically create terrain when you switch back to an mterrain scene. Often when I'm working on my terrain, I need to switch to a different scene for a moment, and when I come back, MTerrain is off again. This would be partially solved by a permanent "create" button somewhere in the UI, but would be better if automatic.
  7. Please switch Region_Size from grid units, to meters. This would solve a LOT of confusion about what this setting does. I think there's an easy way to fake this in the inspector, so that it is displayed to the user as region size in meters without having to change the underlying code. Or at least have a label that also tells you the region size in meters.
  8. Some way to visualise the whole terrain when editing. Maybe a minimap? could be just an image of the whole heightmap, with an outline showing which regions are loaded, and what the editor camera's XZ coordinates are on the minimap? or a super_low_resolution rendering off all regions at once? . I often get lost trying to navigate my terrain. I might be able to draft something using gdscript, but I need help working with the heightmap data, stitching it into one big image.
  9. A tool that allows you to change min_size after you've created the terrain. I can help draft this if I can understand bit more about how the data is stored in the .res files. I understand that all the data would need to be converted and it would be a bit of a heavy operation, but it would be SUPER useful.
  10. A tool to export MGrass data as an image for use in other software e.g. Blender.

BUGFIXES

  1. In PAINT mode, sometimes the mgrass or mterrain node gets deselected. Maybe the plugin can detect when this has happened and automatically disable paint mode? or have an option to lock the selected node so that godot doesn't allow you to deselct the current node being painted

  2. Painting holes in terrain creates problems for future painting because the brush gets stuck at the edges of the hole, and it's very difficult to "Unpaint" a hole. Also, the brushes "collision" uses the whole brush, not just the center of the brush. I should be able to paint up to the edge of the hole, but my mouse gets stopped by the collision (i think).

Questions

  1. What is the downside to smaller min_size? Answer: One of the first reason that we divide terrain to smaller pieces is that we can make disappear the part of the terrain which camera is not looking at! if we make terrain as a single big mesh! it will not possible to make disappear where camera is not looking!

camera_frustum_s

Now when make the min_size smaller you make this smaller pieces more smaller! and thats make more mesh to be disappear when you are looking around! But this has some draw back and as we make more meshinstance we put more pressure on CPU to calculate everything! you need to see which option is good for you! by default min_size is set to 32 meter! and it should be in power of two!

MTerrainMaterial shader with LUT

  1. Create a new MTerrainMaterial and add a new shader with the following code:
shader_type spatial;

uniform sampler2D mterrain_heightmap:filter_nearest;
uniform sampler2D mterrain_normals:filter_nearest;

uniform vec3 region_world_position;
uniform float region_size;
uniform float region_a;
uniform float region_b;
uniform int min_lod;
varying vec3 world_pos;
varying vec2 region_uv;
global uniform sampler2D TerrainLUT;
varying float y;
uniform float terrain_max_height = 740.4;

void vertex(){
	world_pos = (NODE_POSITION_WORLD + VERTEX);
	region_uv = (world_pos.xz - region_world_position.xz)/region_size;
	region_uv = region_uv*region_a + region_b;
	VERTEX.y = texture(mterrain_heightmap, region_uv).r;
	world_pos.y = VERTEX.y;
	vec3 n = texture(mterrain_normals, region_uv ).rgb;	
	n.rb=fma(n.rb,vec2(2.0),vec2(-1.0));
	NORMAL = n;
	//Scale world uv for terrain texture
	world_pos /= 10.0;
	y = VERTEX.y;

}

void fragment(){	
	ALBEDO = texture(TerrainLUT, vec2(y/terrain_max_height,0.)).rgb *0.1;			
}
  1. For the shader_parameter TerrainLUT, create a new GradientTexture1d. Fill it with random (or not random) colors.