I fiddled with some parts of it, and I changed the shader’s heightmap to be a NoiseTexture2D. It changes how the MeshInstance looks, but not the collision.
I suck at coding these images stuff.
Here is my terrain.gd code, not shader:
extends MeshInstance3D
##terrain generation
@onready var col_shape = $StaticBody3D/CollisionShape3D
@export var chunk_size = 100.0
@export var height_ratio = 1.0
@export var colShape_size_ratio = 0.1
var ing = Image.new()
var shape = HeightMapShape3D.new()
@onready var noise = $Noise
func _ready():
col_shape.shape = shape
mesh.size = Vector2(chunk_size, chunk_size)
update_terrain(height_ratio, colShape_size_ratio)
func update_terrain(_height_ratio, _colShape_size_ratio):
material_override.set("shader_param/height_ratio", _height_ratio)
ing = noise.get_texture() ##fixed
ing.convert(Image.FORMAT_RF) ##broken
ing.resize(ing.get_width()*_colShape_size_ratio, ing.get_height()*_colShape_size_ratio) ##also probally broken
var data = ing.get_data().to_float32_array()
for i in range(0, data.size()):
data[i] *= _height_ratio
shape.map_width = ing.get_width()
shape.map_depth = ing.get_height()
shape.map_data = data
var scale_ratio = chunk_size/float(ing.get_width())
col_shape.scale = Vector3(scale_ratio, 1, scale_ratio)
And here is my Terrain node.
If you would like any more detail feel free to ask.
Okay, had a moment to try it. Here’s code that runs for me:
extends Node3D
var ing : Image
func _ready():
## Ok - TextureRect.texture is a "NoiseTexture2D" class.
## Be sure to read the docs on that!
## Also has useful methods you may like.
##
## DOCS:
## Uses the FastNoiseLite library or other noise generators to fill the texture data of
## your desired size.NoiseTexture2D can also generate normal map textures.
## The class uses Threads to generate the texture data internally, so
## Texture2D.get_image() may return null !!!!
## if the generation process has not completed yet.
## In that case, you need to wait for the texture to be generated before
## accessing the image and the generated byte data:
# I renamed the TextureRect to TR to be less confusing on my brain.
await $TR.texture.changed # <-- NB await here !!!!!
ing = $TR.texture.get_image()
ing.resize(ing.get_width(), ing.get_height())
ing.convert(Image.FORMAT_RF)
var data = ing.get_data().to_float32_array() # your way
for i in range(0, data.size()):
print(data[i])
Sorry, but the collision shape is not changing, not sure.
extends MeshInstance3D
##terrain generation
@onready var col_shape = $StaticBody3D/CollisionShape3D
@export var chunk_size = 100.0
@export var height_ratio = 1.0
@export var colShape_size_ratio = 0.1
var ing : Image
var shape = HeightMapShape3D.new()
@onready var noise = $Noise
func _ready():
col_shape.shape = shape
mesh.size = Vector2(chunk_size, chunk_size)
update_terrain(height_ratio, colShape_size_ratio)
func update_terrain(_height_ratio, _colShape_size_ratio):
material_override.set("shader_param/height_ratio", _height_ratio)
await $Noise.texture.changed # <-- NB await here !!!!!
ing = $Noise.texture.get_image()
ing.convert(Image.FORMAT_RF)
ing.resize(ing.get_width()*_colShape_size_ratio, ing.get_height()*_colShape_size_ratio)
var data = ing.get_data().to_float32_array() # your way
for i in range(0, data.size()):
data[i] *= _height_ratio
shape.map_width = ing.get_width()
shape.map_depth = ing.get_height()
shape.map_data = data
var scale_ratio = chunk_size/float(ing.get_width())
col_shape.scale = Vector3(scale_ratio, 1, scale_ratio)
Maybe. I didn’t look at that side of things. Was just solving the null texture problem. Check what numbers you are getting vs. what you expect. Assumptions are always where bugs live.