Skip to content

Commit

Permalink
Merge branch 'johan/firier-fire'
Browse files Browse the repository at this point in the history
This change makes the flames look a lot more like fire.
  • Loading branch information
walles committed Jul 5, 2023
2 parents ed4ddff + 847055e commit 143067d
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 34 deletions.
Binary file modified libloadviz/screenshot.webp
Binary file not shown.
2 changes: 1 addition & 1 deletion libloadviz/src/bin/screenshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fn main() {
let mut anim_writer = AnimWriter::new(
// FIXME: Put this file in the same directory as Cargo.toml
"screenshot.webp",
80.0, // 0-100, pick a number...
90.0, // 0-100, pick a number...
100,
75,
);
Expand Down
92 changes: 59 additions & 33 deletions libloadviz/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::cpuload::CpuLoad;
static BG_COLOR_RGB: &[u8; 3] = &[0x30, 0x30, 0x90];

// Blackbody RGB values from: http://www.vendian.org/mncharity/dir3/blackbody/
static USER_LOAD_COLOR_RGB_COOLER: &[u8; 3] = &[0xff, 0x38, 0x00]; // 1000K
static USER_LOAD_COLOR_RGB_WARMER: &[u8; 3] = &[0xff, 0xb4, 0x6b]; // 3000K
static USER_LOAD_COLOR_RGB_COOLER: &[u8; 3] = &[0xff, 0x38, 0x00]; // 1000K

static CLOUD_COLOR_DARK: &[u8; 3] = &[0x88, 0x88, 0x88];
static CLOUD_COLOR_BRIGHT: &[u8; 3] = &[0xff, 0xff, 0xff];
Expand Down Expand Up @@ -147,12 +147,17 @@ impl Renderer {
width: usize,
height: usize,
) -> Option<[u8; 3]> {
// Higher number = more details.
let detail = 10.0 / width as f32;
// This number determines how uneven the edge of the fire is. Also, it
// decides how much warping happens to the internal base image.
let distortion_detail = 7.0 / width as f32;

// Starting at this fraction of each flame pillar's height, the color will
// start fading towards the background color.
let fadeout_fraction = 0.8;
// This number decides how warped the internal base image is. Try
// setting distortion_detail ^ to almost zero to see the effect of
// changing this number.
let internal_detail = 6.0 / width as f32;

// What fraction of the inside of the fire fades towards transparent?
let transparent_internal_0_to_1 = 0.3;

let distortion_pixel_radius = width.min(height) as f32 / 10.0;

Expand All @@ -175,15 +180,15 @@ impl Renderer {
// Noise output is -1 to 1, deciphered from here:
// https://github.com/amethyst/bracket-lib/blob/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-noise/examples/simplex_fractal.rs#L34-L39
let noise1_m1_to_1 = self.noise.get_noise3d(
detail * pixel_x as f32,
detail * pixel_y_from_bottom as f32,
distortion_detail * pixel_x as f32,
distortion_detail * pixel_y_from_bottom as f32,
dt_seconds,
);

// Pick the load to show
let dx_pixels = noise1_m1_to_1 * distortion_pixel_radius;
let distorted_x = pixel_x as f32 + dx_pixels;
let x_fraction_0_to_1 = distorted_x / (width as f32 - 1.0);
let distorted_pixel_x = pixel_x as f32 + dx_pixels;
let x_fraction_0_to_1 = distorted_pixel_x / (width as f32 - 1.0);
let cpu_load = get_load(viz_loads, x_fraction_0_to_1);

let highest_possible_flame_height_pixels =
Expand All @@ -197,38 +202,59 @@ impl Renderer {
}

let noise2_m1_to_1 = self.noise.get_noise3d(
detail * pixel_x as f32,
detail * pixel_y_from_bottom as f32,
distortion_detail * pixel_x as f32,
distortion_detail * pixel_y_from_bottom as f32,
-dt_seconds - 1.0,
);

// Figure out how to color the current pixel
let dy_pixels = noise2_m1_to_1 * distortion_pixel_radius;
let distorted_y = pixel_y_from_bottom as f32 + dy_pixels;
let y_height_0_to_1 = distorted_y / height as f32;
if y_height_0_to_1 > cpu_load.user_0_to_1 {
let distorted_pixel_y = pixel_y_from_bottom as f32 + dy_pixels;
let y_from_bottom_0_to_1 = distorted_pixel_y / height as f32;
if y_from_bottom_0_to_1 > cpu_load.user_0_to_1 {
return None;
}

// Get the base color
let fraction = y_height_0_to_1 / cpu_load.user_0_to_1;
let color = interpolate(
fraction,
USER_LOAD_COLOR_RGB_WARMER,
USER_LOAD_COLOR_RGB_COOLER,
);

if fraction < fadeout_fraction {
// Too far from the tip, don't fade
return Some(color);
}
// Get a 0-1 noise value for this coordinate, that scrolls up with time
let temperature_0_to_1 = (self.noise.get_noise(
internal_detail * distorted_pixel_x,
internal_detail * distorted_pixel_y - dt_seconds * 2.0,
) + 1.0)
/ 2.0;

// Make the fire cooler the closer the top of the flame we get
let bottom_cooling_layer_thickness_0_to_1 = 0.2;
let cooling_factor = if y_from_bottom_0_to_1 > bottom_cooling_layer_thickness_0_to_1 {
// Cool based on the percentage of the flame height. This looks better in general.
let fraction_of_current_height = y_from_bottom_0_to_1 / cpu_load.user_0_to_1;
1.0 - fraction_of_current_height
} else {
// Cool based on a fraction of the image height. This looks better
// for low CPU loads / flame heights.
let distance_from_top_0_to_1 = cpu_load.user_0_to_1 - y_from_bottom_0_to_1;
1.0 - ((bottom_cooling_layer_thickness_0_to_1 - distance_from_top_0_to_1)
.clamp(0.0, 1.0)
/ bottom_cooling_layer_thickness_0_to_1)
};
let temperature_0_to_1 = temperature_0_to_1 * cooling_factor;

// Colorize based on the noise value
let color = if temperature_0_to_1 < transparent_internal_0_to_1 {
interpolate(
temperature_0_to_1 / transparent_internal_0_to_1,
BG_COLOR_RGB,
USER_LOAD_COLOR_RGB_COOLER,
)
} else {
interpolate(
(temperature_0_to_1 - transparent_internal_0_to_1)
/ (1.0 - transparent_internal_0_to_1),
USER_LOAD_COLOR_RGB_COOLER,
USER_LOAD_COLOR_RGB_WARMER,
)
};

// Fade out
return Some(interpolate(
(fraction - fadeout_fraction) / (1.0 - fadeout_fraction),
&color,
BG_COLOR_RGB,
));
return Some(color);
}
}

Expand Down
Binary file modified macos/loadviz.icns
Binary file not shown.

0 comments on commit 143067d

Please sign in to comment.