[gd_scene load_steps=29 format=2] [ext_resource path="res://material_maker/tools/map_renderer/curvature_generator.gd" type="Script" id=1] [ext_resource path="res://material_maker/tools/map_renderer/map_renderer.gd" type="Script" id=2] [ext_resource path="res://material_maker/tools/map_renderer/bvh_generator.gd" type="Script" id=3] [sub_resource type="World" id=1] [sub_resource type="Shader" id=2] code = "shader_type spatial; render_mode depth_test_disable,depth_draw_always,unshaded,cull_disabled,world_vertex_coords; varying vec3 p; void vertex() { p = NORMAL; VERTEX=vec3(UV, 0.5); } void fragment() { ALBEDO = 0.5*normalize(p)+vec3(0.5); } " [sub_resource type="ShaderMaterial" id=3] shader = SubResource( 2 ) [sub_resource type="Shader" id=24] code = "shader_type spatial; render_mode depth_test_disable,depth_draw_always,unshaded,cull_disabled,world_vertex_coords; varying vec3 p; void vertex() { p = TANGENT; VERTEX=vec3(UV, 0.5); } void fragment() { ALBEDO = 0.5*normalize(p)+vec3(0.5); } " [sub_resource type="ShaderMaterial" id=25] shader = SubResource( 24 ) [sub_resource type="Shader" id=4] code = "shader_type spatial; render_mode depth_test_disable,depth_draw_always,unshaded,cull_disabled,world_vertex_coords; uniform vec3 position = vec3(0.0); uniform vec3 size = vec3(1.0); varying vec3 p; void vertex() { p = (VERTEX-position)/size; VERTEX=vec3(UV, 0.5); } void fragment() { ALBEDO = p; } " [sub_resource type="ShaderMaterial" id=5] shader = SubResource( 4 ) shader_param/position = Vector3( 0, 0, 0 ) shader_param/size = Vector3( 1, 1, 1 ) [sub_resource type="Shader" id=6] code = "shader_type spatial; render_mode depth_test_disable,depth_draw_always,unshaded,cull_disabled,world_vertex_coords; uniform vec3 position = vec3(0.0); uniform vec3 size = vec3(1.0); void vertex() { VERTEX=vec3(UV, 0.5); } void fragment() { ALBEDO = vec3(1.0); } " [sub_resource type="ShaderMaterial" id=7] shader = SubResource( 6 ) shader_param/position = Vector3( 0, 0, 0 ) shader_param/size = Vector3( 1, 1, 1 ) [sub_resource type="Shader" id=8] code = "shader_type spatial; render_mode depth_test_disable,depth_draw_always,unshaded,cull_disabled,world_vertex_coords; varying float curvature; void vertex() { curvature = dot(COLOR, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0)); VERTEX=vec3(UV, 0.5); } void fragment() { ALBEDO = vec3(curvature); } " [sub_resource type="ShaderMaterial" id=9] shader = SubResource( 8 ) [sub_resource type="Shader" id=10] code = "shader_type spatial; render_mode cull_disabled, unshaded; uniform sampler2D bvh_data; uniform float max_dist; uniform int iteration = 1; uniform sampler2D prev_iteration_tex; varying vec3 normal; varying vec3 model_vert; void vertex() { model_vert = VERTEX; normal = NORMAL; VERTEX = vec3(UV, 0.5); } float intersect_aabb(vec3 ray_origin, vec3 ray_dir, vec3 box_min, vec3 box_max, bool solid) { vec3 tMin = (box_min - ray_origin) / ray_dir; vec3 tMax = (box_max - ray_origin) / ray_dir; vec3 t1 = min(tMin, tMax); vec3 t2 = max(tMin, tMax); float tNear = max(max(t1.x, t1.y), t1.z); float tFar = min(min(t2.x, t2.y), t2.z); if(tNear > tFar || (tFar < 0.0 && tNear < 0.0)) { return -1.0; } if(tNear < 0.0) { float temp = tNear; tNear = tFar; tFar = temp; tNear *= float(!solid); } return tNear; } float intersects_triangle(vec3 ray_start, vec3 ray_dir, vec3 v0, vec3 v1, vec3 v2) { vec3 e1 = v1 - v0; vec3 e2 = v2 - v0; vec3 h = cross(ray_dir, e2); float a = dot(e1, h); if (abs(a) < 0.000001) { // Parallel test. return -1.0; } float f = 1.0 / a; vec3 s = ray_start - v0; float u = f * dot(s, h); if (u < 0.0 || u > 1.0) { return -1.0; } vec3 q = cross(s, e1); float v = f * dot(ray_dir, q); if (v < 0.0 || u + v > 1.0) { return -1.0; } // At this stage we can compute t to find out where // the intersection point is on the line. float t = f * dot(e2, q); return t > 0.0000001 ? t : -1.0; } vec4 get_data(int index) { ivec2 data_size = textureSize(bvh_data, 0); return texelFetch(bvh_data, ivec2( index % data_size.x, index / data_size.x ), 0); } float intersects_bvh(vec3 ray_start, vec3 ray_dir, out vec3 normal_hit) { int offset_to_nodes = int(get_data(0)[0]); vec4 root_data_0 = get_data(int(get_data(1)[0]) + offset_to_nodes); vec4 root_data_1 = get_data(int(get_data(1)[0]) + offset_to_nodes + 1); float t = intersect_aabb(ray_start, ray_dir, root_data_0.xyz, root_data_1.xyz, false); if(t == -1.0) { return 65536.0; } float prev_hit = t; t = 65536.0; // Set to large number vec3 tri[3] = vec3[]; int min_node_idx = 0; int stack_point = 0; ivec3 node_stack[128] = ivec3[]; // ivec3 int curr_node_idx = 0; bool moving_up = false; for(int i = 0; i < 256; i++) { if(moving_up && stack_point <= 0) { break; } int node_data_off = int(get_data(1 + curr_node_idx)[0]) + offset_to_nodes; vec4 node_data_0 = get_data(node_data_off); vec4 node_data_1 = get_data(node_data_off + 1); int level = int(node_data_0[3]); if(!moving_up) { // Moving down node hierarchy if(node_data_1[3] > 0.0) { // Is a leaf node for(int j = node_data_off + 2; j < node_data_off + 2 + int(node_data_1[3]) * 3; j+=3) { vec3 tri_a = get_data(j).xyz; vec3 tri_b = get_data(j + 1).xyz; vec3 tri_c = get_data(j + 2).xyz; float tri_t = intersects_triangle(ray_start, ray_dir, tri_a, tri_b, tri_c ); if(tri_t != -1.0) { if(tri_t < t) { tri[0] = tri_a; tri[1] = tri_b; tri[2] = tri_c; // print(curr_node_idx) min_node_idx = curr_node_idx; } t = min(t, tri_t); } } stack_point -= 1; if(stack_point <= 0) { break; } if(node_stack[stack_point][1] == level) { // next node in stack is sibling if(t < intBitsToFloat(node_stack[stack_point][0])) { // no chance to get better hit from sibling stack_point -= 1; moving_up = true; } } else { moving_up = true; } prev_hit = intBitsToFloat(node_stack[stack_point][0]); curr_node_idx = node_stack[stack_point][2]; } else { // Push self onto stack node_stack[stack_point] = ivec3(floatBitsToInt(prev_hit), level, curr_node_idx); stack_point += 1; ivec2 child_indices = ivec2(get_data(node_data_off + 2).xy); int left_data_off = int(get_data(1 + child_indices[0])[0]) + offset_to_nodes; vec4 left_data_0 = get_data(left_data_off); vec4 left_data_1 = get_data(left_data_off + 1); int right_data_off = int(get_data(1 + child_indices[1])[0]) + offset_to_nodes; vec4 right_data_0 = get_data(right_data_off); vec4 right_data_1 = get_data(right_data_off + 1); float t_left = intersect_aabb(ray_start, ray_dir, left_data_0.xyz, left_data_1.xyz, true); float t_right = intersect_aabb(ray_start, ray_dir, right_data_0.xyz, right_data_1.xyz, true); if(t_right == -1.0 && t_left != -1.0) { // only left node hit prev_hit = t_left; curr_node_idx = child_indices[0]; } else if(t_left == -1.0 && t_right != -1.0) { // only right node hit prev_hit = t_right; curr_node_idx = child_indices[1]; } else if(t_left < t_right && t_left != -1.0) { // left node hits closer node_stack[stack_point] = ivec3(floatBitsToInt(t_right), int(right_data_0[3]), child_indices[1]); stack_point += 1; prev_hit = t_left; curr_node_idx = child_indices[0]; } else if(t_right <= t_left && t_right != -1.0) { // right node hits closer node_stack[stack_point] = ivec3(floatBitsToInt(t_left), int(left_data_0[3]), child_indices[0]); stack_point += 1; prev_hit = t_right; curr_node_idx = child_indices[1]; } else { // no hit stack_point -= 2; if(stack_point <= 0) { break; } if(node_stack[stack_point][1] == level) { // next node in stack is sibling if(t < intBitsToFloat(node_stack[stack_point][0])) { // no chance to get better hit from sibling stack_point -= 1; moving_up = true; } } else { moving_up = true; } prev_hit = intBitsToFloat(node_stack[max(stack_point, 0)][0]); curr_node_idx = node_stack[max(stack_point, 0)][2]; } } } else { // Moving up hierarchy stack_point -= 1; if(stack_point <= 0) { break; } if(node_stack[stack_point][1] == level) { // next node in stack is sibling if(t < intBitsToFloat(node_stack[stack_point][0])) { // no chance to get better hit from sibling stack_point -= 1; } else { moving_up = false; } } prev_hit = intBitsToFloat(node_stack[max(stack_point, 0)][0]); curr_node_idx = node_stack[max(stack_point, 0)][2]; } } normal_hit = normalize(cross(tri[2] - tri[0], tri[1] - tri[0])); return t; } vec3 random_hemi_point(vec3 rand, vec3 norm) { const float PI = 3.141592653; float ang1 = (rand.x + 1.0) * PI; // [-1..1) -> [0..2*PI) float u = rand.y; // [-1..1), cos and acos(2v-1) cancel each other out, so we arrive at [-1..1) float u2 = u * u; float sqrt1MinusU2 = sqrt(1.0 - u2); float x = sqrt1MinusU2 * cos(ang1); float y = sqrt1MinusU2 * sin(ang1); float z = u; vec3 v = vec3(x, y, z); return v * sign(dot(v, norm)); } float rand(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); } void fragment() { vec3 model_norm = normalize(normal) * sign(max_dist); vec3 ddx_vert = dFdx(model_vert); vec3 ddy_vert = dFdy(model_vert); vec3 true_normal = normalize(cross(ddy_vert, ddx_vert)) * sign(max_dist); vec3 ray_start = model_vert + model_norm * 0.0001; vec3 ray_dir; for(int i = 0; i < 5; i++) { ray_dir = random_hemi_point(vec3( rand(SCREEN_UV + float(iteration)), rand(-SCREEN_UV.yx + float(iteration)), 0.0 ), model_norm); if(dot(ray_dir, true_normal) > 0.0) { break; } } float hit = intersects_bvh(ray_start, ray_dir, NORMAL); if(hit == 65536.0 || hit < 0.0) { hit = abs(max_dist);//ALPHA = 0.0; } hit /= abs(max_dist); // float weight = dot(model_norm, ray_dir); ALBEDO = mix(texture(prev_iteration_tex, SCREEN_UV).rgb, vec3(hit), 1.0/float(iteration)); } " [sub_resource type="ViewportTexture" id=11] viewport_path = NodePath(".") [sub_resource type="ShaderMaterial" id=12] resource_local_to_scene = true shader = SubResource( 10 ) shader_param/max_dist = -2.0 shader_param/iteration = 1 shader_param/prev_iteration_tex = SubResource( 11 ) [sub_resource type="Shader" id=13] code = "shader_type spatial; render_mode unshaded, cull_disabled; uniform sampler2D tex; uniform int radius = 3; uniform float size = 512.0; void vertex() { VERTEX = vec3(UV, 0.5); } void fragment() { if(texture(tex, SCREEN_UV).a == 0.0) { discard; } vec3 color = vec3(0.0); float weight = 0.0; for(int y = -radius; y < radius+1; y++) { for(int x = -radius; x < radius+1; x++) { vec4 col = texture(tex, SCREEN_UV + vec2(ivec2(x, y)) / size, 0); color += col.rgb * col.a; weight += col.a; } } ALBEDO = color / weight; }" [sub_resource type="ShaderMaterial" id=14] resource_local_to_scene = true shader = SubResource( 13 ) shader_param/radius = 0 shader_param/size = 512.0 shader_param/tex = SubResource( 11 ) [sub_resource type="Shader" id=15] code = "shader_type canvas_item; render_mode blend_disabled; uniform sampler2D tex; uniform float size = 512.0; const int STEPS = 64; vec4 dilate_distance_h(vec2 uv) { vec2 e = vec2(1.0/size, 0.0); float d = float(STEPS)/size; float rv = 0.0; vec2 source_uv; vec4 source_color; for (int i = 0; i < STEPS; ++i) { source_uv = uv+float(i)*e; source_color = texture(tex, source_uv); if (source_color.a >= 1.0) { rv = 1.0-float(i)*e.x/d; break; } source_uv = uv-float(i)*e; source_color = texture(tex, source_uv); if (source_color.a >= 1.0) { rv = 1.0-float(i)*e.x/d; break; } } return vec4(source_color.rgb, rv); } void fragment() { COLOR = dilate_distance_h(UV); } " [sub_resource type="ShaderMaterial" id=16] shader = SubResource( 15 ) shader_param/size = 512.0 [sub_resource type="Shader" id=17] code = "shader_type canvas_item; render_mode blend_disabled; uniform sampler2D tex; uniform float size = 512.0; const int STEPS = 64; vec4 dilate_distance_v(vec2 uv) { vec2 e = vec2(0.0, 1.0/size); float d = float(STEPS)/size; vec4 p = texture(tex, uv); for (int i = 0; i < STEPS; ++i) { vec2 dx = float(i)*e; vec4 p2 = texture(tex, uv+dx); if (p2.a > p.a) { p2.a = 1.0-sqrt((1.0-p2.a)*(1.0-p2.a)+dx.y*dx.y/d/d); 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)+dx.y*dx.y/d/d); p = mix(p, p2, step(p.a, p2.a)); } } return p; } void fragment() { COLOR = dilate_distance_v(UV); } " [sub_resource type="ShaderMaterial" id=18] shader = SubResource( 17 ) shader_param/size = 512.0 [sub_resource type="Shader" id=19] code = "shader_type canvas_item; render_mode blend_disabled; uniform sampler2D tex; uniform float size = 512.0; const int STEPS = 125; vec4 dilate_distance_h(vec2 uv) { vec2 e = vec2(1.0/size, 0.0); float d = size/float(STEPS); float rv = 0.0; float found = 0.0; vec2 source_uv; vec4 source_color; int steps = min(STEPS, int(size)/2); for (int i = 0; i < steps; ++i) { source_uv = uv+float(i)*e; source_color = texture(tex, source_uv); if (source_color.a >= 0.5) { rv = float(i); found = 1.0; break; } source_uv = uv-float(i)*e; source_color = texture(tex, source_uv); if (source_color.a >= 0.5) { rv = -float(i); found = 1.0; break; } } return vec4(vec3(0.5+0.5*rv*e.x*d), found); } void fragment() { COLOR = dilate_distance_h(UV); } " [sub_resource type="ShaderMaterial" id=20] shader = SubResource( 19 ) shader_param/size = 512.0 [sub_resource type="Shader" id=21] code = "shader_type canvas_item; render_mode blend_disabled; uniform sampler2D tex; uniform float size = 512.0; const int STEPS = 64; vec4 best(vec4 last, vec2 uv, float dy) { vec2 p = texture(tex, uv+dy).ar; float d = size/float(STEPS); float dx = (p.y-0.5)/d; if (p.x > 0.5) { float d_2 = dx*dx+dy*dy; if (d_2 < last.y) { last = vec4(1.0, d_2, p.y, dy); } } return last; } vec4 dilate_distance_v(vec2 uv) { float e = 1.0/size; float d = size/float(STEPS); vec4 p = vec4(texture(tex, uv).arr, 0.0); if (p.x < 0.5) { p.y = 1.0; } else { p.y = (p.y-0.5)/d; p.y *= p.y; } int steps = min(STEPS, int(size)/2); for (int i = 0; i < steps; ++i) { float dy = float(i)*e; p = best(p, uv, dy); p = best(p, uv, -dy); } return vec4(p.z, 0.5+0.5*p.w*d, 0.0, p.x); } void fragment() { COLOR = dilate_distance_v(UV); } " [sub_resource type="ShaderMaterial" id=22] shader = SubResource( 21 ) shader_param/size = 512.0 [sub_resource type="PrismMesh" id=23] [node name="MapRenderer" type="Viewport"] size = Vector2( 2048, 2048 ) own_world = true world = SubResource( 1 ) transparent_bg = true keep_3d_linear = true render_target_update_mode = 0 script = ExtResource( 2 ) mesh_normal_material = SubResource( 3 ) mesh_tangent_material = SubResource( 25 ) inv_uv_material = SubResource( 5 ) white_material = SubResource( 7 ) curvature_material = SubResource( 9 ) ao_material = SubResource( 12 ) denoise_pass = SubResource( 14 ) dilate_pass1 = SubResource( 16 ) dilate_pass2 = SubResource( 18 ) seams_pass1 = SubResource( 20 ) seams_pass2 = SubResource( 22 ) [node name="MeshInstance" type="MeshInstance" parent="."] mesh = SubResource( 23 ) material/0 = SubResource( 5 ) __meta__ = { "_editor_description_": "" } [node name="Camera" type="Camera" parent="."] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0.5, 6 ) projection = 1 [node name="CurvatureGenerator" type="Node" parent="."] script = ExtResource( 1 ) [node name="BVHGenerator" type="Node" parent="."] script = ExtResource( 3 )