GodotShade/mesh_generation_from_image.gd
Guillaume Vern a342f96089 init project
2025-10-07 16:20:44 +02:00

81 lines
4.7 KiB
GDScript

extends MeshInstance3D
@export var resolution_scaling = 1
@export var height_scale = 500 * resolution_scaling
func _ready():
DebugDraw3D.debug_enabled = true
create_mesh()
set_material()
func create_mesh():
var heightmap_texture = ResourceLoader.load("res://Rolling Hills Height Map 1k/Rolling Hills Height Map.png")
var heightmap_image: Image = heightmap_texture.get_image()
heightmap_image.convert(Image.FORMAT_RF)
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
for i in range(-(heightmap_image.get_height() / resolution_scaling / 2), heightmap_image.get_height() / resolution_scaling / 2):
for j in range(-(heightmap_image.get_width() / resolution_scaling / 2), heightmap_image.get_width() / resolution_scaling / 2):
create_quad(st, Vector2(i, j), heightmap_image)
st.index()
mesh = st.commit()
func set_material():
var material = StandardMaterial3D.new()
material.vertex_color_use_as_albedo = true
set_surface_override_material(0, material)
func create_quad(st: SurfaceTool, position: Vector2, heightmap_image: Image):
var height1 = heightmap_image.get_pixel((position.x + 1) * resolution_scaling + heightmap_image.get_width() / 2, position.y * resolution_scaling + heightmap_image.get_height() / 2)
var vertexPosition1 = Vector3(position.x * resolution_scaling + resolution_scaling, height1.get_luminance() * height_scale, position.y * resolution_scaling )
var height2 = heightmap_image.get_pixel(position.x * resolution_scaling + heightmap_image.get_width() / 2, (position.y + 1) * resolution_scaling + heightmap_image.get_height() / 2)
var vertexPosition2 = Vector3(position.x * resolution_scaling , height2.get_luminance() * height_scale, position.y * resolution_scaling + resolution_scaling)
var height3 = heightmap_image.get_pixel(position.x * resolution_scaling + heightmap_image.get_width() / 2, position.y * resolution_scaling + heightmap_image.get_height() / 2)
var vertexPosition3 = Vector3(position.x * resolution_scaling , height3.get_luminance() * height_scale, position.y * resolution_scaling )
var height4 = heightmap_image.get_pixel((position.x + 1) * resolution_scaling + heightmap_image.get_width() / 2, (position.y + 1) * resolution_scaling + heightmap_image.get_height() / 2)
var vertexPosition4 = Vector3(position.x * resolution_scaling + resolution_scaling, height4.get_luminance() * height_scale, position.y * resolution_scaling + resolution_scaling)
var height5 = heightmap_image.get_pixel(position.x * resolution_scaling + heightmap_image.get_width() / 2, (position.y + 1) * resolution_scaling + heightmap_image.get_height() / 2)
var vertexPosition5 = Vector3(position.x * resolution_scaling, height5.get_luminance() * height_scale, position.y * resolution_scaling + resolution_scaling)
var height6 = heightmap_image.get_pixel((position.x + 1) * resolution_scaling + heightmap_image.get_width() / 2, position.y * resolution_scaling + heightmap_image.get_height() / 2)
var vertexPosition6 = Vector3(position.x * resolution_scaling + resolution_scaling, height6.get_luminance() * height_scale, position.y * resolution_scaling)
var normal1 = -Vector3(vertexPosition2 - vertexPosition1).cross(Vector3(vertexPosition3 - vertexPosition1)).normalized()
var normal2 = -Vector3(vertexPosition5 - vertexPosition4).cross(Vector3(vertexPosition6 - vertexPosition4)).normalized()
st.set_color(Color.from_rgba8(normal1.x * 255, normal1.y * 255, normal1.z * 255))
st.set_normal(normal1.normalized())
st.add_vertex(vertexPosition1)
st.set_color(Color.from_rgba8(normal1.x * 255, normal1.y * 255, normal1.z * 255))
st.set_normal(normal1.normalized())
st.add_vertex(vertexPosition2)
st.set_color(Color.from_rgba8(normal1.x * 255, normal1.y * 255, normal1.z * 255))
st.set_normal(normal1.normalized())
st.add_vertex(vertexPosition3)
st.set_color(Color.from_rgba8(normal2.x * 255, normal2.y * 255, normal2.z * 255))
st.set_normal(normal2.normalized())
st.add_vertex(vertexPosition4)
st.set_color(Color.from_rgba8(normal2.x * 255, normal2.y * 255, normal2.z * 255))
st.set_normal(normal2.normalized())
st.add_vertex(vertexPosition5)
st.set_color(Color.from_rgba8(normal2.x * 255, normal2.y * 255, normal2.z * 255))
st.set_normal(normal2.normalized())
st.add_vertex(vertexPosition6)
func _process(delta):
if Input.is_action_pressed("ShowNormals"):
if mesh == null:
return
for surface_index in mesh.get_surface_count():
var arrays = mesh.surface_get_arrays(surface_index)
if arrays.size() == 0:
continue
var vertices = arrays[Mesh.ARRAY_VERTEX]
var normals = arrays[Mesh.ARRAY_NORMAL]
for i in vertices.size():
DebugDraw3D.draw_line(vertices[i], normals[i] + vertices[i] , Color.from_rgba8(normals[i].x * 255, normals[i].y * 255, normals[i].z * 255))