0
\$\begingroup\$

I'm trying to create procedurally generated terrain, it works but it just uses simple textures. The lower area below sea level I want to add a water material instead of a simple texture. How can I achieve this? enter image description here I am using the following code to procedurally generate terrain:

class_name HTerrainGenerator # Import classes const HTerrain: Resource = preload("res://addons/zylann.hterrain/hterrain.gd") const HTerrainData: Resource = preload("res://addons/zylann.hterrain/hterrain_data.gd") const HTerrainTextureSet: Resource = preload("res://addons/zylann.hterrain/hterrain_texture_set.gd") var grass_texture: Resource = load("res://Levels/Textures/T_ground_forest_grass_03_BC_H.PNG") var sand_texture: Resource = load("res://Levels/Textures/T_ground_sand_03_BC_H.PNG") var mud_texture: Resource = load("res://Levels/Textures/t_mud_01_d_1k.PNG") var terrian_seed: int = randi_range(0, 999999999999999999) func generate_terrain() -> HTerrain: # Create terrain resource and give it a size. # It must be either 513, 1025, 2049 or 4097. var terrain_data: HTerrainData = HTerrainData.new() terrain_data.resize(513) var noise: FastNoiseLite = FastNoiseLite.new() noise.seed = terrian_seed var noise_multiplier = 10.0 # affects the height of the terrain # Get access to terrain maps var heightmap: Image = terrain_data.get_image(HTerrainData.CHANNEL_HEIGHT) var normalmap: Image = terrain_data.get_image(HTerrainData.CHANNEL_NORMAL) var splatmap: Image = terrain_data.get_image(HTerrainData.CHANNEL_SPLAT) # Generate terrain maps for z in heightmap.get_height(): for x in heightmap.get_width(): # Generate height var h = noise_multiplier * noise.get_noise_2d(x, z) # Getting normal by generating extra heights directly from noise, # so map borders won't have seams in case you stitch them var h_right = noise_multiplier * noise.get_noise_2d(x + 0.1, z) var h_forward = noise_multiplier * noise.get_noise_2d(x, z + 0.1) var normal: Vector3 = Vector3(h - h_right, 0.1, h_forward - h).normalized() # Generate texture amounts var splat: Color = splatmap.get_pixel(x, z) var slope: float = 4.0 * normal.dot(Vector3.UP) - 2.0 # Sand on the slopes the higher value the more sand shows var sand_amount: float = clamp(2.1 - slope, 0.0, 1.0) # Mud below sea level var mud_amount: float = clamp(0.0 - h, 0.0, 1.0) splat = splat.lerp(Color(0,1,0,0), sand_amount) splat = splat.lerp(Color(0,0,1,0), mud_amount) heightmap.set_pixel(x, z, Color(h, 0, 0)) normalmap.set_pixel(x, z, HTerrainData.encode_normal(normal)) splatmap.set_pixel(x, z, splat) # Commit modifications so they get uploaded to the graphics card var modified_region: Rect2 = Rect2(Vector2(), heightmap.get_size()) terrain_data.notify_region_change(modified_region, HTerrainData.CHANNEL_HEIGHT) terrain_data.notify_region_change(modified_region, HTerrainData.CHANNEL_NORMAL) terrain_data.notify_region_change(modified_region, HTerrainData.CHANNEL_SPLAT) # Create texture set var texture_set: HTerrainTextureSet = HTerrainTextureSet.new() texture_set.set_mode(HTerrainTextureSet.MODE_TEXTURES) texture_set.insert_slot(-1) texture_set.set_texture(0, HTerrainTextureSet.TYPE_ALBEDO_BUMP, grass_texture) texture_set.insert_slot(-1) texture_set.set_texture(1, HTerrainTextureSet.TYPE_ALBEDO_BUMP, sand_texture) texture_set.insert_slot(-1) texture_set.set_texture(2, HTerrainTextureSet.TYPE_ALBEDO_BUMP, mud_texture) # Create terrain node var terrain: HTerrain = HTerrain.new() terrain.set_shader_type(HTerrain.SHADER_CLASSIC4_LITE) terrain.set_data(terrain_data) terrain.set_texture_set(texture_set) terrain.position = Vector3(0, 0, 0) return terrain func reload(terrain: HTerrain): terrain.data.reload() terrain.update_collider() 
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$
  1. Divide your map into an NxN grid of cells. Resolution is up to you.
  2. Check at sea level height whether you are above or below the terrain at this [x,y] (or [x,z]) point (will require some point-triangle checks).
  3. If you are below the terrain surface, texture stays the same.
  4. If you are above the terrain surface, change the texture data.

The finer you make the grid, the better the result will be. You can optimise by using a quadtree to get finer edges around the shorelines, without processing as many [x,y] locations as you would with a uniform grid.

If water surface height differs across the map, you can also make a coarse grid for that, and process according to which grid cell (height) you are in / at.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.