mirror of
https://github.com/CrispyPin/julia-fractal-renderer.git
synced 2024-11-22 10:00:26 +01:00
add export options
This commit is contained in:
parent
7c7d56e868
commit
c76f340fd7
2 changed files with 44 additions and 27 deletions
|
@ -20,15 +20,15 @@ pub enum FillStyle {
|
||||||
pub fn render(q: &RenderOptions, color: (u8, u8, u8)) -> RgbImage {
|
pub fn render(q: &RenderOptions, color: (u8, u8, u8)) -> RgbImage {
|
||||||
let mut img = RgbImage::new(q.width, q.height);
|
let mut img = RgbImage::new(q.width, q.height);
|
||||||
|
|
||||||
let width = q.width as f64;
|
let width: f64 = q.width.into();
|
||||||
let height = q.height as f64;
|
let height: f64 = q.height.into();
|
||||||
let ppu = width / q.unit_width;
|
let ppu = width / q.unit_width;
|
||||||
|
|
||||||
for y in 0..q.height {
|
for y in 0..q.height {
|
||||||
for x in 0..q.width {
|
for x in 0..q.width {
|
||||||
let pixel = {
|
let pixel = {
|
||||||
let x = (x as f64 - width / 2.0) / ppu;
|
let x = (f64::from(x) - width / 2.0) / ppu;
|
||||||
let y = (y as f64 - height / 2.0) / ppu;
|
let y = (f64::from(y) - height / 2.0) / ppu;
|
||||||
|
|
||||||
let iter = julia(x, y, q.cx, q.cy, q.max_iterations);
|
let iter = julia(x, y, q.cx, q.cy, q.max_iterations);
|
||||||
if q.fill_style == FillStyle::Black && iter == q.max_iterations {
|
if q.fill_style == FillStyle::Black && iter == q.max_iterations {
|
||||||
|
@ -57,5 +57,5 @@ fn julia(mut x: f64, mut y: f64, cx: f64, cy: f64, max_iter: u32) -> u32 {
|
||||||
);
|
);
|
||||||
iter += 1;
|
iter += 1;
|
||||||
}
|
}
|
||||||
return iter;
|
iter
|
||||||
}
|
}
|
||||||
|
|
61
src/main.rs
61
src/main.rs
|
@ -2,7 +2,7 @@
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use eframe::{
|
use eframe::{
|
||||||
egui::{self, RichText, Slider},
|
egui::{self, DragValue, RichText, Slider, TextureOptions},
|
||||||
epaint::{TextureHandle, Vec2},
|
epaint::{TextureHandle, Vec2},
|
||||||
Frame, NativeOptions,
|
Frame, NativeOptions,
|
||||||
};
|
};
|
||||||
|
@ -40,9 +40,9 @@ struct JuliaGUI {
|
||||||
impl JuliaGUI {
|
impl JuliaGUI {
|
||||||
fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
||||||
let preview = cc.egui_ctx.load_texture(
|
let preview = cc.egui_ctx.load_texture(
|
||||||
"my-image",
|
"preview_image",
|
||||||
egui::ColorImage::from_rgb([1, 1], &[0, 0, 0]),
|
egui::ColorImage::from_rgb([1, 1], &[0, 0, 0]),
|
||||||
Default::default(),
|
TextureOptions::default(),
|
||||||
);
|
);
|
||||||
let preview_quality = RenderOptions {
|
let preview_quality = RenderOptions {
|
||||||
width: 512,
|
width: 512,
|
||||||
|
@ -60,7 +60,7 @@ impl JuliaGUI {
|
||||||
render_options: preview_quality,
|
render_options: preview_quality,
|
||||||
preview_render_ms: 0.0,
|
preview_render_ms: 0.0,
|
||||||
export_render_ms: f64::NAN,
|
export_render_ms: f64::NAN,
|
||||||
export_res_multiplier: 4,
|
export_res_multiplier: 8,
|
||||||
export_iterations: 512,
|
export_iterations: 512,
|
||||||
export_name: String::from("julia_set.png"),
|
export_name: String::from("julia_set.png"),
|
||||||
settings_changed: true,
|
settings_changed: true,
|
||||||
|
@ -75,7 +75,7 @@ impl JuliaGUI {
|
||||||
[preview.width() as usize, preview.height() as usize],
|
[preview.width() as usize, preview.height() as usize],
|
||||||
preview.as_bytes(),
|
preview.as_bytes(),
|
||||||
),
|
),
|
||||||
Default::default(),
|
TextureOptions::default(),
|
||||||
);
|
);
|
||||||
self.preview_render_ms = start_time.elapsed().unwrap().as_micros() as f64 / 1000.0;
|
self.preview_render_ms = start_time.elapsed().unwrap().as_micros() as f64 / 1000.0;
|
||||||
}
|
}
|
||||||
|
@ -89,8 +89,8 @@ impl JuliaGUI {
|
||||||
..self.render_options.clone()
|
..self.render_options.clone()
|
||||||
};
|
};
|
||||||
let image = render(&settings, self.color);
|
let image = render(&settings, self.color);
|
||||||
if let Err(e) = image.save(&self.export_name) {
|
if let Err(err) = image.save(&self.export_name) {
|
||||||
println!("Error exporting render: {e}");
|
println!("Error exporting render: {err}");
|
||||||
}
|
}
|
||||||
self.export_render_ms = start_time.elapsed().unwrap().as_micros() as f64 / 1000.0;
|
self.export_render_ms = start_time.elapsed().unwrap().as_micros() as f64 / 1000.0;
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ impl eframe::App for JuliaGUI {
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.exact_width(200.0)
|
.exact_width(200.0)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
|
ui.label(RichText::new("Fractal settings").heading());
|
||||||
if ui.button("Update preview").clicked() {
|
if ui.button("Update preview").clicked() {
|
||||||
self.settings_changed = true;
|
self.settings_changed = true;
|
||||||
}
|
}
|
||||||
|
@ -115,18 +116,6 @@ impl eframe::App for JuliaGUI {
|
||||||
self.preview_render_ms
|
self.preview_render_ms
|
||||||
));
|
));
|
||||||
|
|
||||||
if ui
|
|
||||||
.button(format!("Render to '{}'", &self.export_name))
|
|
||||||
.clicked()
|
|
||||||
{
|
|
||||||
self.export_render();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.label(format!(
|
|
||||||
"last exported render took {:.2}ms",
|
|
||||||
self.export_render_ms
|
|
||||||
));
|
|
||||||
|
|
||||||
ui.label("CX:");
|
ui.label("CX:");
|
||||||
let set_cx = ui.add(Slider::new(&mut self.render_options.cx, -2.0..=2.0));
|
let set_cx = ui.add(Slider::new(&mut self.render_options.cx, -2.0..=2.0));
|
||||||
ui.label("CY:");
|
ui.label("CY:");
|
||||||
|
@ -151,13 +140,41 @@ impl eframe::App for JuliaGUI {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.label(RichText::new("Quality settings").heading());
|
ui.label("Preview iterations:");
|
||||||
ui.label("iterations:");
|
|
||||||
let set_iter = ui.add(
|
let set_iter = ui.add(
|
||||||
Slider::new(&mut self.render_options.max_iterations, 5..=256)
|
Slider::new(&mut self.render_options.max_iterations, 5..=256)
|
||||||
.clamp_to_range(false),
|
.clamp_to_range(false),
|
||||||
);
|
);
|
||||||
//todo resolution
|
|
||||||
|
ui.label(RichText::new("Render settings").heading());
|
||||||
|
ui.label("preview resolution:");
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
let set_width = ui.add(DragValue::new(&mut self.render_options.width));
|
||||||
|
ui.label("x");
|
||||||
|
let set_height = ui.add(DragValue::new(&mut self.render_options.height));
|
||||||
|
if set_width.changed() || set_height.changed() {
|
||||||
|
self.settings_changed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.label("Export iterations:");
|
||||||
|
ui.add(Slider::new(&mut self.export_iterations, 5..=1024).clamp_to_range(false));
|
||||||
|
ui.label("Resolution multiplier:");
|
||||||
|
ui.add(Slider::new(&mut self.export_res_multiplier, 1..=32));
|
||||||
|
ui.label(format!(
|
||||||
|
"Export resolution: {}x{}",
|
||||||
|
self.export_res_multiplier * self.render_options.width,
|
||||||
|
self.export_res_multiplier * self.render_options.height
|
||||||
|
));
|
||||||
|
|
||||||
|
let render_button = ui.button(format!("Render to '{}'", &self.export_name));
|
||||||
|
if render_button.clicked() {
|
||||||
|
self.export_render();
|
||||||
|
}
|
||||||
|
ui.label(format!(
|
||||||
|
"last exported render took {:.2}ms",
|
||||||
|
self.export_render_ms
|
||||||
|
));
|
||||||
|
|
||||||
if set_cx.changed()
|
if set_cx.changed()
|
||||||
|| set_cy.changed() || set_unit_width.changed()
|
|| set_cy.changed() || set_unit_width.changed()
|
||||||
|
|
Loading…
Reference in a new issue