From 4d1fa40f195401927a32f20444fcdf8b506fb379 Mon Sep 17 00:00:00 2001 From: Rodz Labs Date: Mon, 25 Nov 2024 08:05:58 +0100 Subject: [PATCH] Mesh map generation updates and adjency map prototype --- .../engine/nodes/gen_meshmap.gd | 6 ++ .../adjacency_dilate_compute.tres | 25 ++++++ .../map_generator/adjacency_generator.gd | 80 +++++++++++++++++++ .../map_generator/dilate_1_compute.tres | 46 ----------- .../map_generator/dilate_2_compute.tres | 46 ----------- .../map_generator/dilate_compute.tres | 24 ++++++ .../map_generator/map_generator.gd | 38 ++++++--- addons/material_maker/map_generator/test.gd | 7 +- 8 files changed, 163 insertions(+), 109 deletions(-) create mode 100644 addons/material_maker/map_generator/adjacency_dilate_compute.tres create mode 100644 addons/material_maker/map_generator/adjacency_generator.gd delete mode 100644 addons/material_maker/map_generator/dilate_1_compute.tres delete mode 100644 addons/material_maker/map_generator/dilate_2_compute.tres create mode 100644 addons/material_maker/map_generator/dilate_compute.tres diff --git a/addons/material_maker/engine/nodes/gen_meshmap.gd b/addons/material_maker/engine/nodes/gen_meshmap.gd index 454874261..5f9c34fec 100644 --- a/addons/material_maker/engine/nodes/gen_meshmap.gd +++ b/addons/material_maker/engine/nodes/gen_meshmap.gd @@ -74,6 +74,12 @@ const MESH_MAPS : Array[Dictionary] = [ output_type="f", map="thickness", output="texture($TEXTURE, $UV).r" + }, + { + name="Adjacency", + output_type="rgb", + map="adjacency", + output="texture($TEXTURE, $UV).rgb" } ] diff --git a/addons/material_maker/map_generator/adjacency_dilate_compute.tres b/addons/material_maker/map_generator/adjacency_dilate_compute.tres new file mode 100644 index 000000000..d2c9a738c --- /dev/null +++ b/addons/material_maker/map_generator/adjacency_dilate_compute.tres @@ -0,0 +1,25 @@ +[gd_resource type="Resource" script_class="TextResource" load_steps=2 format=3 uid="uid://bbqkm42mc6w1f"] + +[ext_resource type="Script" path="res://addons/material_maker/engine/text_resource.gd" id="1_wb5c8"] + +[resource] +script = ExtResource("1_wb5c8") +text = "#version 450 + +layout(local_size_x = @LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in; + +@DECLARATIONS + +layout(set = 3, binding = 0, std140) restrict buffer MM { + int mm_chunk_y; +}; + +void main() { + ivec2 pixel = ivec2(gl_GlobalInvocationID.xy)+ivec2(0, mm_chunk_y); + vec2 image_size = imageSize(OUTPUT_TEXTURE); + vec2 uv = (pixel+vec2(0.5, 0.5))/image_size; + vec2 dilated_uv = texture(seams_map, uv).xy; + vec4 color = mix(texture(tex, dilated_uv), vec4(uv, 0.0, 1.0), step(length(uv-dilated_uv), 0.001)); + imageStore(OUTPUT_TEXTURE, pixel, color); +} +" diff --git a/addons/material_maker/map_generator/adjacency_generator.gd b/addons/material_maker/map_generator/adjacency_generator.gd new file mode 100644 index 000000000..e56d91a11 --- /dev/null +++ b/addons/material_maker/map_generator/adjacency_generator.gd @@ -0,0 +1,80 @@ +extends Object +class_name MMAdjacencyGenerator + + +# Code ported from: +# https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/intern/cycles/blender/blender_mesh.cpp#L541 + + +var progress : int = 0 +var progress_total : int = 0 + + +func get_progress() -> float: + if progress_total == 0: + return 0.0 + return float(progress)/float(progress_total) + +func generate(mesh: Mesh) -> Mesh: + var b_mesh : MeshDataTool = MeshDataTool.new() + if not mesh is ArrayMesh: + b_mesh.create_from_surface(mesh.create_outline(0.0), 0) + else: + b_mesh.create_from_surface(mesh, 0) + + progress = 0 + progress_total = b_mesh.get_vertex_count() + + var num_verts = b_mesh.get_vertex_count() + if (num_verts == 0): + return Mesh.new() + + for i in b_mesh.get_vertex_count(): + b_mesh.set_vertex_normal(i, Vector3(0, 0, 0)) + + var found_edges : Array[int] = [] + for i in b_mesh.get_edge_count(): + if b_mesh.get_edge_faces(i).size() > 1: + continue + if i in found_edges: + continue + var i0 : int = b_mesh.get_edge_vertex(i, 0) + var i1 : int = b_mesh.get_edge_vertex(i, 1) + var pi0 : Vector3 = b_mesh.get_vertex(i0) + var pi1 : Vector3 = b_mesh.get_vertex(i1) + print("Edge ", i, " (", pi0, ", ", pi1,")") + for j in range(i+1, b_mesh.get_edge_count()): + var j0 : int = b_mesh.get_edge_vertex(j, 0) + var j1 : int = b_mesh.get_edge_vertex(j, 1) + var pj0 = b_mesh.get_vertex(j0) + var pj1 = b_mesh.get_vertex(j1) + var uvi0 : Vector2 = b_mesh.get_vertex_uv(i0) + var uvi1 : Vector2 = b_mesh.get_vertex_uv(i1) + if pi0 == pj0 and pi1 == pj1: + print(" Edge ", j, " matches") + var uvj0 : Vector2 = b_mesh.get_vertex_uv(j0) + var uvj1 : Vector2 = b_mesh.get_vertex_uv(j1) + b_mesh.set_vertex_normal(i0, Vector3(uvj0.x, uvj0.y, 0)) + b_mesh.set_vertex_normal(i1, Vector3(uvj1.x, uvj1.y, 0)) + b_mesh.set_vertex_normal(j0, Vector3(uvi0.x, uvi0.y, 0)) + b_mesh.set_vertex_normal(j1, Vector3(uvi1.x, uvi1.y, 0)) + elif pi0 == pj1 and pi1 == pj0: + print(" Edge ", j, " matches backwards") + var uvj0 : Vector2 = b_mesh.get_vertex_uv(j0) + var uvj1 : Vector2 = b_mesh.get_vertex_uv(j1) + b_mesh.set_vertex_normal(i1, Vector3(uvj0.x, uvj0.y, 0)) + b_mesh.set_vertex_normal(i0, Vector3(uvj1.x, uvj1.y, 0)) + b_mesh.set_vertex_normal(j1, Vector3(uvi0.x, uvi0.y, 0)) + b_mesh.set_vertex_normal(j0, Vector3(uvi1.x, uvi1.y, 0)) + else: + b_mesh.set_vertex_normal(i0, Vector3(uvi0.x, uvi0.y, 1)) + b_mesh.set_vertex_normal(i1, Vector3(uvi1.x, uvi1.y, 1)) + continue + print(" Edge ", j, " (", pj0, ", ", pj1,")") + found_edges.append(j) + break + + var new_mesh : ArrayMesh = ArrayMesh.new() + var _err := b_mesh.commit_to_surface(new_mesh) + + return new_mesh diff --git a/addons/material_maker/map_generator/dilate_1_compute.tres b/addons/material_maker/map_generator/dilate_1_compute.tres deleted file mode 100644 index 29d5ef350..000000000 --- a/addons/material_maker/map_generator/dilate_1_compute.tres +++ /dev/null @@ -1,46 +0,0 @@ -[gd_resource type="Resource" script_class="TextResource" load_steps=2 format=3 uid="uid://dxnfyyjnmyhvg"] - -[ext_resource type="Script" path="res://addons/material_maker/engine/text_resource.gd" id="1_liu37"] - -[resource] -script = ExtResource("1_liu37") -text = "#version 450 - -layout(local_size_x = @LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in; - -@DECLARATIONS - -layout(set = 3, binding = 0, std140) restrict buffer MM { - int mm_chunk_y; -}; - -vec4 dilate_distance_h(vec2 uv, float size) { - vec2 e = vec2(1.0/size, 0.0); - float d = float(pixels)/size; - float rv = 0.0; - vec2 src_uv; - vec4 src_color; - for (int i = 0; i < pixels; ++i) { - src_uv = uv+float(i)*e; - src_color = texture(tex, src_uv); - if (src_color.a >= 1.0) { - rv = 1.0-float(i)*e.x/d; - break; - } - src_uv = uv-float(i)*e; - src_color = texture(tex, src_uv); - if (src_color.a >= 1.0) { - rv = 1.0-float(i)*e.x/d; - break; - } - } - return vec4(src_color.rgb, rv); -} - -void main() { - ivec2 pixel = ivec2(gl_GlobalInvocationID.xy)+ivec2(0, mm_chunk_y); - vec2 image_size = imageSize(OUTPUT_TEXTURE); - vec2 uv = (pixel+vec2(0.5, 0.5))/image_size; - imageStore(OUTPUT_TEXTURE, pixel, dilate_distance_h(uv, image_size.x)); -} -" diff --git a/addons/material_maker/map_generator/dilate_2_compute.tres b/addons/material_maker/map_generator/dilate_2_compute.tres deleted file mode 100644 index ad141a411..000000000 --- a/addons/material_maker/map_generator/dilate_2_compute.tres +++ /dev/null @@ -1,46 +0,0 @@ -[gd_resource type="Resource" script_class="TextResource" load_steps=2 format=3 uid="uid://3n8psiiv6i43"] - -[ext_resource type="Script" path="res://addons/material_maker/engine/text_resource.gd" id="1_rsni6"] - -[resource] -script = ExtResource("1_rsni6") -text = "#version 450 - -layout(local_size_x = @LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in; - -@DECLARATIONS - -layout(set = 3, binding = 0, std140) restrict buffer MM { - int mm_chunk_y; -}; - -vec4 dilate_distance_v(vec2 uv, float size) { - vec2 e = vec2(0.0, 1.0/size); - float d = float(pixels)/size; - vec4 p = texture(tex, uv); - for (int i = 0; i < pixels; ++i) { - vec2 dx = float(i)*e; - float dy_squared = dx.y*dx.y/d/d; - vec4 p2 = texture(tex, uv+dx); - if (p2.a > p.a) { - p2.a = 1.0-sqrt((1.0-p2.a)*(1.0-p2.a)+dy_squared); - p = mix(p, p2, step(p.a, p2.a)); - } - p2 = texture(tex, uv-dx); - if (p2.a > p.a) { - p2.a = 1.0-sqrt((1.0-p2.a)*(1.0-p2.a)+dy_squared); - p = mix(p, p2, step(p.a, p2.a)); - } - } - return p; -} - -void main() { - ivec2 pixel = ivec2(gl_GlobalInvocationID.xy)+ivec2(0, mm_chunk_y); - vec2 image_size = imageSize(OUTPUT_TEXTURE); - vec2 uv = (pixel+vec2(0.5, 0.5))/image_size; - vec4 color = dilate_distance_v(uv, image_size.x); - color.a = step(0.0, color.a); - imageStore(OUTPUT_TEXTURE, pixel, color); -} -" diff --git a/addons/material_maker/map_generator/dilate_compute.tres b/addons/material_maker/map_generator/dilate_compute.tres new file mode 100644 index 000000000..5d8d805d5 --- /dev/null +++ b/addons/material_maker/map_generator/dilate_compute.tres @@ -0,0 +1,24 @@ +[gd_resource type="Resource" script_class="TextResource" load_steps=2 format=3 uid="uid://btn8qmquhmf05"] + +[ext_resource type="Script" path="res://addons/material_maker/engine/text_resource.gd" id="1_8tcbo"] + +[resource] +script = ExtResource("1_8tcbo") +text = "#version 450 + +layout(local_size_x = @LOCAL_SIZE, local_size_y = 1, local_size_z = 1) in; + +@DECLARATIONS + +layout(set = 3, binding = 0, std140) restrict buffer MM { + int mm_chunk_y; +}; + +void main() { + ivec2 pixel = ivec2(gl_GlobalInvocationID.xy)+ivec2(0, mm_chunk_y); + vec2 image_size = imageSize(OUTPUT_TEXTURE); + vec2 uv = (pixel+vec2(0.5, 0.5))/image_size; + vec4 color = texture(tex, texture(seams_map, uv).xy); + imageStore(OUTPUT_TEXTURE, pixel, color); +} +" diff --git a/addons/material_maker/map_generator/map_generator.gd b/addons/material_maker/map_generator/map_generator.gd index b8f9a489f..ebd540e15 100644 --- a/addons/material_maker/map_generator/map_generator.gd +++ b/addons/material_maker/map_generator/map_generator.gd @@ -14,15 +14,16 @@ const MAP_DEFINITIONS : Dictionary = { type="simple", vertex = "position_vertex", fragment = "common_fragment", - postprocess=["dilate_1", "dilate_2"] + postprocess=["dilate"] }, - normal = { type="simple", vertex = "normal_vertex", fragment = "normal_fragment", postprocess=["dilate_1", "dilate_2"] }, - tangent = { type="simple", vertex = "tangent_vertex", fragment = "normal_fragment", postprocess=["dilate_1", "dilate_2"] }, - ambient_occlusion = { type="bvh", vertex = "ao_vertex", fragment = "ao_fragment", mode=0, postprocess=["dilate_1", "dilate_2"] }, - bent_normals = { type="bvh", vertex = "ao_vertex", fragment = "ao_fragment", mode=1, postprocess=["dilate_1", "dilate_2"] }, - thickness = { type="bvh", vertex = "ao_vertex", fragment = "ao_fragment", mode=2, postprocess=["dilate_1", "dilate_2"] }, - curvature = { type="curvature", vertex = "curvature_vertex", fragment = "common_fragment", postprocess=["dilate_1", "dilate_2"] }, - seams = { type="simple", vertex = "position_vertex", fragment = "common_fragment", postprocess=["seams_1", "seams_2"] } + normal = { type="simple", vertex = "normal_vertex", fragment = "normal_fragment", postprocess=["dilate"] }, + tangent = { type="simple", vertex = "tangent_vertex", fragment = "normal_fragment", postprocess=["dilate"] }, + ambient_occlusion = { type="bvh", vertex = "ao_vertex", fragment = "ao_fragment", mode=0, postprocess=["dilate"] }, + bent_normals = { type="bvh", vertex = "ao_vertex", fragment = "ao_fragment", mode=1, postprocess=["dilate"] }, + thickness = { type="bvh", vertex = "ao_vertex", fragment = "ao_fragment", mode=2, postprocess=["dilate"] }, + curvature = { type="curvature", vertex = "curvature_vertex", fragment = "common_fragment", postprocess=["dilate"] }, + seams = { type="simple", vertex = "position_vertex", fragment = "common_fragment", postprocess=["seams_1", "seams_2"] }, + adjacency = { type="adjacency", vertex = "normal_vertex", fragment = "common_fragment", postprocess=["adjacency_dilate"] }, } @@ -82,6 +83,16 @@ static func generate(mesh : Mesh, map : String, size : int, texture : MMTexture) mesh_pipeline.mesh = thread.wait_to_finish() await mesh_pipeline.set_shader(vertex_shader, fragment_shader) await mesh_pipeline.render(Vector2i(size, size), 3, texture) + "adjacency": + var adjacency_generator : MMAdjacencyGenerator = MMAdjacencyGenerator.new() + var thread : Thread = Thread.new() + thread.start(adjacency_generator.generate.bind(mesh)) + while thread.is_alive(): + await mm_globals.get_tree().process_frame + progress.set_progress(adjacency_generator.get_progress()) + mesh_pipeline.mesh = thread.wait_to_finish() + await mesh_pipeline.set_shader(vertex_shader, fragment_shader) + await mesh_pipeline.render(Vector2i(size, size), 3, texture) "bvh": mesh_pipeline.mesh = mesh var bvh : MMTexture = MMTexture.new() @@ -132,6 +143,10 @@ static func generate(mesh : Mesh, map : String, size : int, texture : MMTexture) postprocess_pipeline.clear() postprocess_pipeline.add_parameter_or_texture("tex", "sampler2D", texture) postprocess_pipeline.add_parameter_or_texture("pixels", "int", pixels) + match p: + "adjacency_dilate", "dilate": + var seams_map : MMTexture = await get_map(mesh, "seams", false, true) + postprocess_pipeline.add_parameter_or_texture("seams_map", "sampler2D", seams_map) await postprocess_pipeline.set_shader(load("res://addons/material_maker/map_generator/"+p+"_compute.tres").text, 3) await postprocess_pipeline.render(texture, Vector2i(size, size)) #texture.save_to_file("d:/debug_%d.png" % debug_index) @@ -140,7 +155,7 @@ static func generate(mesh : Mesh, map : String, size : int, texture : MMTexture) static var busy : bool = false -static func get_map(mesh : Mesh, map : String) -> MMTexture: +static func get_map(mesh : Mesh, map : String, force_generate : bool = false, parallel : bool = false) -> MMTexture: if mesh == null: if error_texture == null: error_texture = MMTexture.new() @@ -150,10 +165,12 @@ static func get_map(mesh : Mesh, map : String) -> MMTexture: return error_texture if ! mesh_maps.has(mesh): mesh_maps[mesh] = {} + if force_generate: + mesh_maps[mesh].erase(map) while true: if mesh_maps[mesh].has(map): break - if not busy: + if parallel or not busy: busy = true var texture : MMTexture = MMTexture.new() mesh_maps[mesh][map] = texture @@ -162,4 +179,3 @@ static func get_map(mesh : Mesh, map : String) -> MMTexture: break await mm_globals.get_tree().process_frame return mesh_maps[mesh][map] as MMTexture - diff --git a/addons/material_maker/map_generator/test.gd b/addons/material_maker/map_generator/test.gd index 6e917c9d2..9aed18895 100644 --- a/addons/material_maker/map_generator/test.gd +++ b/addons/material_maker/map_generator/test.gd @@ -14,12 +14,7 @@ func _ready(): func show_map(map_name : String): var mesh = load("res://material_maker/meshes/suzanne.obj") - var t : MMTexture - if false: - t = MMTexture.new() - await MMMapGenerator.generate(mesh, map_name, 512, t) - else: - t = await MMMapGenerator.get_map(mesh, map_name) + var t : MMTexture = await MMMapGenerator.get_map(mesh, map_name, true) texture = await t.get_texture() func _on_maps_item_selected(index):