material-maker/material_maker/tools/map_renderer/map_renderer.tscn

634 lines
15 KiB
Plaintext

[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 )