diff --git a/src/gui.rs b/src/gui.rs index ca283d0..25182a2 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -57,10 +57,10 @@ fn ui_system( ui.label("ca iterations"); ui.add( egui::DragValue::new(&mut shader_configurator.shader_configs[3].iterations) - .range(0..=50), + .range(0..=100), ); }); - ui.add(egui::Slider::new(&mut params.ca_thresh, 0.1..=20.).text("thresh")); + ui.add(egui::Slider::new(&mut params.ca_thresh, 0.0..=1.).text("thresh")); ui.add(egui::Slider::new(&mut params.ca_search_radius, 0.1..=6.).text("search radius")); }); diff --git a/src/main.rs b/src/main.rs index 0aebb48..ca0f877 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,7 +64,7 @@ impl Default for ParamsUniform { warp_amount: 0.0, warp_scale: 0.0, noise_weight: 0.53, - ca_thresh: 7.5, + ca_thresh: 0.17, ca_search_radius: 3.8 } } diff --git a/src/shaders/ca.wgsl b/src/shaders/ca.wgsl index fed70e9..0657fa7 100644 --- a/src/shaders/ca.wgsl +++ b/src/shaders/ca.wgsl @@ -1,3 +1,7 @@ +#import compute::noise +#import compute::utils + + struct Params { dimensions: u32, radius: f32, @@ -16,10 +20,15 @@ struct Params { ca_search_radius: f32 } +@group(0) @binding(0) var params: Params; +@group(0) @binding(1) var input_texture: texture_storage_2d; +@group(0) @binding(2) var output_texture: texture_storage_2d; + fn get_weighted_neighbor_count(x: i32, y: i32, radius: f32) -> f32 { var found = 0.0; let dim = i32(params.dimensions); let r = i32(ceil(radius)); + var count = 0.0; for(var i = -r; i <= r; i++) { for(var j = -r; j <= r; j++) { @@ -46,16 +55,34 @@ fn get_weighted_neighbor_count(x: i32, y: i32, radius: f32) -> f32 { // Weight by distance from center let weight = 1.0 - sqrt(dist_sq) / radius; found += v * weight; + count += 1.0; } } - return found; + + let normed: f32 = found / count; + + return normed; } +// fn probb(v: f32) -> bool{ +// if(v <= 0){ +// return false; +// } +// if(v >= 1){ +// return true; +// } + +// var rand = noise::rand11(f32(x * y * y)); +// return rand < v; +// } + +// regarding input: +// r contains generated terrain +// g contains distance field from center +// b contains distance field from edges +// a contains weighted noise -@group(0) @binding(0) var params: Params; -@group(0) @binding(1) var input_texture: texture_storage_2d; -@group(0) @binding(2) var output_texture: texture_storage_2d; // @compute @workgroup_size(16, 16) // fn main(@builtin(global_invocation_id) global_id: vec3) { @@ -66,45 +93,36 @@ fn get_weighted_neighbor_count(x: i32, y: i32, radius: f32) -> f32 { // return; // } + + // let upos = vec2(i32(x), i32(y)); // let current = textureLoad(input_texture, upos); - +// let edge_dist = current.b; // let nze = current.a; - + // let scaled_radius = params.ca_search_radius * (8.0 / (f32(params.dimensions) / 128.0)); -// let neighbor_weight = get_weighted_neighbor_count(i32(x), i32(y), scaled_radius); - -// let base_threshold = params.ca_thresh * (scaled_radius / 4.0); - -// // Increased stability bias for more persistence -// let stability_bias = 0.25; -// let threshold = select( -// base_threshold, -// base_threshold * (1.0 - stability_bias), -// nze > 0.5 -// ); +// let nbs = get_weighted_neighbor_count(i32(x), i32(y), scaled_radius); -// // Wider transition zone -// let transition_width = 0.2 * base_threshold; -// let diff = neighbor_weight - threshold; - -// // Use the transition value directly instead of as a selector -// let transition = 1.0 - smoothstep(-transition_width, transition_width, diff); - -// // Strong bias toward maintaining current state unless transition is significant -// let persistence = 0.7; -// let v = select( -// transition, -// nze, -// abs(nze - transition) < persistence -// ); +// var thresh = params.ca_thresh; -// var result = current.x - nze; -// result = clamp(result, 0., 1.); -// textureStore(output_texture, upos, vec4f(result, current.y, current.z, nze)); -// } +// // true means we are a cave and we will be subtracted from the planet +// var selector = nbs > thresh; + +// var rand = noise::rand11(f32(x * y * y)); + +// var caves = select( +// 0., +// 1., +// selector +// ); +// // caves = caves + edge_dist; + +// var result = current.r - caves; + +// textureStore(output_texture, upos, vec4f(current.x, current.y, current.z, caves)); +// } @compute @workgroup_size(16, 16) fn main(@builtin(global_invocation_id) global_id: vec3) { let x = global_id.x; @@ -116,25 +134,45 @@ fn main(@builtin(global_invocation_id) global_id: vec3) { let upos = vec2(i32(x), i32(y)); let current = textureLoad(input_texture, upos); - + let edge_dist = current.b; let nze = current.a; - // let result = nze; + let scaled_radius = params.ca_search_radius * (8.0 / (f32(params.dimensions) / 128.0)); + let nbs = get_weighted_neighbor_count(i32(x), i32(y), scaled_radius); - // let caves = 1.0; + var thresh = params.ca_thresh; - let nbs = get_weighted_neighbor_count(i32(x), i32(y), params.ca_search_radius); + // Generate base cave selector from cellular automata + var selector = nbs > thresh; + + // Get random value + var rand = noise::rand11(f32(x * y * y)); + + let seed = vec2f(f32(x), f32(y)); + var n = noise::fbm(seed * 0.01); + n = n * 0.5 + 0.5; + n = n - 0.3; + n = n * 0.1; + // Create an exponential edge falloff factor + // pow(x, n) where n > 1 creates exponential curve + // Higher power = sharper falloff + let edge_power = n * 5.; // Adjust this to control falloff sharpness + let edge_scale = n; // Adjust this to control where falloff starts + let edge_factor = pow(clamp(edge_dist / edge_scale, 0.0, 1.0), edge_power); + + // Only allow cave formation if random value is less than edge factor + selector = selector && (rand < edge_factor); var caves = select( 0., 1., - nbs > params.ca_thresh + selector ); var result = current.r - caves; - - // // result = current.z - result; - // result = clamp (result, 0., 1.); - + textureStore(output_texture, upos, vec4f(current.x, current.y, current.z, caves)); -} \ No newline at end of file +} + +// r, g, and b are left as is +// caves are added to a \ No newline at end of file diff --git a/src/shaders/extract.wgsl b/src/shaders/extract.wgsl index 582c8df..3ec1369 100644 --- a/src/shaders/extract.wgsl +++ b/src/shaders/extract.wgsl @@ -29,5 +29,6 @@ fn main(@builtin(global_invocation_id) global_id: vec3) { var r = current.r - current.a; r = clamp(r, 0., 1.); - textureStore(output_texture, upos, vec4f(r,current.y,current.z,1.)); + // textureStore(output_texture, upos, vec4f(r,r,r,1.)); + textureStore(output_texture, upos, vec4f(r, 0., 0., 1.0)); } diff --git a/src/shaders/generate_circle.wgsl b/src/shaders/generate_circle.wgsl index 1443fca..8df8f89 100644 --- a/src/shaders/generate_circle.wgsl +++ b/src/shaders/generate_circle.wgsl @@ -66,7 +66,7 @@ fn main(@builtin(global_invocation_id) global_id: vec3) { let dim = params.dimensions; - var pos = vec2f( + var normd_pos = vec2f( f32(x) / f32(dim), f32(y) / f32(dim) ); @@ -75,7 +75,7 @@ fn main(@builtin(global_invocation_id) global_id: vec3) { let seed_mult = 10.0; let center = vec2(0.5, 0.5); - let angle = atan2(pos.x - center.x, pos.y - center.y); + let angle = atan2(normd_pos.x - center.x, normd_pos.y - center.y); let seed = vec2f(cos(angle), sin(angle)); var n = noise::fbm((seed * seed_mult * params.noise_scale) + params.noise_offset); @@ -88,16 +88,23 @@ fn main(@builtin(global_invocation_id) global_id: vec3) { var result = mix(n, m, params.mix); let r = params.radius * 0.4 + result; - let dist = distance(pos, center); + let dist_to_center = distance(normd_pos, center); let upos = vec2(i32(x), i32(y)); - let v = select(0.0, 1.0, dist <= r); + let v = select(0.0, 1.0, dist_to_center <= r); - pos = pos - center; - let mag = length(pos); - pos = vec2f(mag, 0.0); + normd_pos = normd_pos - center; + let mag = length(normd_pos); + normd_pos = vec2f(mag, 0.0); let edge = vec2f(r, 0.0); + let dist_to_edge = distance(normd_pos, edge); - textureStore(output_texture, upos, vec4(v , dist, distance(pos, edge), 1.)); + textureStore(output_texture, upos, vec4(v , dist_to_center, dist_to_edge, 1.)); } +// r contains generated terrain +// g contains distance field from center +// b contains distance field from edges +// a is unused + + diff --git a/src/shaders/pre_ca_noise.wgsl b/src/shaders/pre_ca_noise.wgsl index 47f58a5..4f32916 100644 --- a/src/shaders/pre_ca_noise.wgsl +++ b/src/shaders/pre_ca_noise.wgsl @@ -33,12 +33,13 @@ fn main(@builtin(global_invocation_id) global_id: vec3) { } let pos = vec2f(f32(x), f32(y)); let upos = vec2(i32(x), i32(y)); - let v = noise::rand11(f32(x * y)); + // let v = noise::rand11(f32(x * (y*y))); + let v = noise::rand11(f32(x ^ (y << 16))); let s = select(0.,1.,v <= params.noise_weight); - - var current = textureLoad(input_texture, upos); - // var result = current.x-s; - // result = clamp(result, 0., 1.); + textureStore(output_texture, upos, vec4f(current.x, current.y, current.z, f32(s))); -} \ No newline at end of file +} + +// r, g, and b are left as is +// noise is added to a \ No newline at end of file