diff --git a/shaders/galaxy.wgsl b/shaders/galaxy.wgsl index 806f164..27eedf8 100644 --- a/shaders/galaxy.wgsl +++ b/shaders/galaxy.wgsl @@ -25,6 +25,9 @@ struct Params { fh:f32, fcx:f32, fcy:f32, + red:f32, + green:f32, + blue2:f32, }; @group(0) @binding(1) @@ -52,16 +55,46 @@ fn fbmslow(p: vec2) -> f32 { fn noise(p: vec2, iTime: f32) -> f32 { return fbmslow(p + iTime * params.gamma); } +fn random(vec: vec2) -> f32 { + return fract(sin(dot(vec, vec2(12.9898, 78.233))) * 43758.5453); +} +fn hsv2rgb(c: vec3) -> vec3 { + var h: f32 = c.x * 6.0; + var s: f32 = c.y; + var v: f32 = c.z; + var i: i32 = i32(floor(h)); + var f: f32 = h - f32(i); + var p: f32 = v * (1.0 - s); + var q: f32 = v * (1.0 - s * f); + var t: f32 = v * (1.0 - s * (1.0 - f)); + var rgb: vec3; + if (i == 0) { + rgb = vec3(v, t, p); + } else if (i == 1) { + rgb = vec3(q, v, p); + } else if (i == 2) { + rgb = vec3(p, v, t); + } else if (i == 3) { + rgb = vec3(p, q, v); + } else if (i == 4) { + rgb = vec3(t, p, v); + } else { + rgb = vec3(v, p, q); + } + return rgb; +} +fn screenBlend(a: vec3, b: vec3) -> vec3 { + return 1.0 - ((1.0 - a) * (1.0 - b)); +} @fragment fn main(@builtin(position) FragCoord: vec4) -> @location(0) vec4 { - let PI: f32 = 3.1415926535897932384626433832795; let resolution: vec2 = vec2(1920.0, 1080.0); let lightDirection: vec3 = normalize(vec3(1.0, 1.0, 1.0)); let zoomLevel: f32 = params.blue; var uv: vec2 = (FragCoord.xy / resolution) - vec2(0.5, 0.5); let distanceFromCenter: f32 = length(uv) * params.alpha; let flow: vec2 = vec2(noise(uv, u_time.time), noise(uv + vec2(0.1, 0.1), u_time.time)); - let timeFactor: f32 =params.theta* u_time.time; + let timeFactor: f32 = params.theta * u_time.time; let adjustedTime: f32 = timeFactor + (params.delta + sin(timeFactor)) * 0.1 / (distanceFromCenter + 0.07); let sineTime: f32 = sin(adjustedTime); let cosineTime: f32 = cos(adjustedTime); @@ -72,17 +105,34 @@ fn main(@builtin(position) FragCoord: vec4) -> @location(0) vec4 { var color2: f32 = params.noise2; var color3: f32 = 0.0; var point: vec3 = vec3(0.0, 0.0, 0.0); + var starColor: vec3 = vec3(0.0, 0.0, 0.0); for (var i: i32 = 0; i < 150; i = i + 1) { point = params.eta * f32(i) * vec3(uv, params.fh); - let stars = oscillate(0.1,params.color*PI, 20.5, u_time.time); - point = point + vec3(0.1, 0.01, -params.fw*PI - sin(timeFactor * 0.1) * stars); + let stars = oscillate(0.1, params.color * PI, 20.5, u_time.time); + point = point + vec3(0.1, 0.01, -params.fw * PI - sin(timeFactor * 0.1) * stars); for (var j: i32 = 0; j < 11; j = j + 1) { point = abs(point) / dot(point, point) - params.psi; } - let pointIntensity: f32 = dot(point, point) *params.omega; - color1 = color1 + pointIntensity * (params.rho+ sin(distanceFromCenter * 13.0 + 3.5 - timeFactor * 2.0)); + let pointIntensity: f32 = dot(point, point) * params.omega; + color1 = color1 + pointIntensity * (params.rho + sin(distanceFromCenter * 13.0 + 3.5 - timeFactor * 2.0)); color2 = color2 + pointIntensity * (params.phi + sin(distanceFromCenter * 13.5 + 2.2 - timeFactor * 3.0)); color3 = color3 + pointIntensity * (2.4 + sin(distanceFromCenter * 14.5 + 1.5 - timeFactor * 2.5)); + + let starfield: vec2 = vec2( + fract(sin(f32(i) * 12.9898 + 78.233) * 43758.5453), + fract(cos(f32(i) * 4.898) * 23421.631) + ); + let distance: f32 = length(uv - starfield); + if (distance < 0.01) { + let starInt: f32 = 1.0 - distance / 0.01; + let starHue: f32 = random(starfield); + let starSatur: f32 = 0.7 + 0.3 * random(starfield + vec2(1.0, 1.0)); + let lumos: f32 = starInt * 0.5 + 0.5; + var starRgb: vec3 = hsv2rgb(vec3(starHue, starSatur, lumos)); + let flare: f32 = 0.5 + 0.5 * sin(u_time.time * 5.0 * random(starfield + vec2(360.0, 2.0))); + starRgb *= flare; + starColor += starRgb * starInt; + } } baseColor = (3.1 / (params.fcx + zoomLevel)) * length(vec2(point.x, point.y)) * params.sigma; color1 = color1 * 0.5; @@ -93,7 +143,10 @@ fn main(@builtin(position) FragCoord: vec4) -> @location(0) vec4 { let sundot: f32 = dot(lightDirection, direction); var finalColor: vec3 = vec3(baseColor, (color1 + baseColor) * 0.25, color2); finalColor = finalColor + color3 * 2.9; - finalColor.g = finalColor.g + color3 * 0.45; + finalColor.g = finalColor.g + color2 * params.green; + finalColor.b = finalColor.b + color2 * params.blue2; + finalColor.r = finalColor.r + color2 * params.red; + finalColor = screenBlend(finalColor, starColor); finalColor = applyGamma(finalColor, 0.5); return vec4(finalColor, 1.0); } \ No newline at end of file diff --git a/src/galaxy.rs b/src/galaxy.rs index 90e2203..48d9136 100644 --- a/src/galaxy.rs +++ b/src/galaxy.rs @@ -30,6 +30,9 @@ struct Settings { fh:f32, fcx:f32, fcy:f32, + red:f32, + green:f32, + blue2:f32, show_ui: bool, } #[repr(C)] @@ -77,8 +80,12 @@ fn update(app: &App, model: &mut Model, update: Update) { ui.add(egui::Slider::new(&mut model.settings.fh, -PI..=10.0).text("zm2")); ui.add(egui::Slider::new(&mut model.settings.fcx, -PI..=PI).text("scB")); ui.add(egui::Slider::new(&mut model.settings.fcy, 0.0..=1.0).text("sun")); + ui.add(egui::Slider::new(&mut model.settings.red, 0.0..=1.0).text("RED")); + ui.add(egui::Slider::new(&mut model.settings.green, 0.0..=1.0).text("GREEN")); + ui.add(egui::Slider::new(&mut model.settings.blue2, 0.0..=1.0).text("BLUE")); + }); - let params_data = [model.settings.lambda, model.settings.theta, model.settings.sigma,model.settings.gamma,model.settings.alpha,model.settings.delta,model.settings.eta,model.settings.rho,model.settings.phi,model.settings.psi,model.settings.omega,model.settings.blue,model.settings.noise,model.settings.noise2,model.settings.color,model.settings.fw,model.settings.fh,model.settings.fcx,model.settings.fcy]; + let params_data = [model.settings.lambda, model.settings.theta, model.settings.sigma,model.settings.gamma,model.settings.alpha,model.settings.delta,model.settings.eta,model.settings.rho,model.settings.phi,model.settings.psi,model.settings.omega,model.settings.blue,model.settings.noise,model.settings.noise2,model.settings.color,model.settings.fw,model.settings.fh,model.settings.fcx,model.settings.fcy,model.settings.red,model.settings.green,model.settings.blue2]; let params_bytes = bytemuck::cast_slice(¶ms_data); app.main_window().queue().write_buffer(&model.params_uniform, 0, ¶ms_bytes); } @@ -136,7 +143,7 @@ fn model(app: &App) -> Model { ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, - min_binding_size: wgpu::BufferSize::new((std::mem::size_of::() * 19) as _), + min_binding_size: wgpu::BufferSize::new((std::mem::size_of::() * 22) as _), }, count: None, }], @@ -189,8 +196,12 @@ fn model(app: &App) -> Model { fh:1.0, fcx:1.3, fcy:0.18, + red:0.4, + green:0.7, + blue2:0.7, + }; - let params_data = [settings.lambda, settings.theta, settings.sigma,settings.gamma,settings.alpha,settings.delta,settings.eta,settings.rho,settings.phi,settings.psi,settings.omega,settings.blue,settings.noise,settings.noise2,settings.color,settings.fw,settings.fh,settings.fcx,settings.fcy]; + let params_data = [settings.lambda, settings.theta, settings.sigma,settings.gamma,settings.alpha,settings.delta,settings.eta,settings.rho,settings.phi,settings.psi,settings.omega,settings.blue,settings.noise,settings.noise2,settings.color,settings.fw,settings.fh,settings.fcx,settings.fcy,settings.red,settings.green,settings.blue2]; let params_bytes = bytemuck::cast_slice(¶ms_data); let params_uniform = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Params Uniform"),