summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-12-17 18:16:53 -0500
committerpommicket <pommicket@gmail.com>2022-12-17 18:16:53 -0500
commitcfb773fa87a4fbb76d8eed4b595e6d17ff8a698e (patch)
tree2d9b648927be3d123e2783f9db599024cc0708eb /src
parenta9666d1a34c25999b14d7ab345648d7066322035 (diff)
big State object to clean up code
Diffstat (limited to 'src')
-rw-r--r--src/fshader_test.glsl11
-rw-r--r--src/main.rs197
-rw-r--r--src/win.rs75
3 files changed, 188 insertions, 95 deletions
diff --git a/src/fshader_test.glsl b/src/fshader_test.glsl
index 95458ee..9e41d92 100644
--- a/src/fshader_test.glsl
+++ b/src/fshader_test.glsl
@@ -3,6 +3,15 @@
%COMMON%
%SDF%
+IN vec2 pos;
+
+vec4 rand(vec2 coord) {
+ // this seems to give pretty good quality noise for |coord| < 2
+ vec4 a = sin((coord.xyyx + vec4(3.0)) * (coord.xyxy + vec4(4.0)) * 100.0 + 0.5832) * 1618.0;
+ vec4 b = sin((coord.xyyx + vec4(3.0)) * (coord.xyxy + vec4(4.0)) * 222.0 + 5.1339) * 2412.0;
+ return vec4(fract(a.xy + a.zw), fract(b.xy + b.zw));
+}
+
void main() {
- gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = vec4(rand(pos));//sdf(8.0 * rand(pos).xyz - 4.0));
}
diff --git a/src/main.rs b/src/main.rs
index a489271..7dccf9f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,11 +10,11 @@
- AA quality
- # iterations, distance cutoff
---release---
+- switch framebuffer texture to grayscale
- show that θ = σ(z) / sqrt(x² + y²)
(x,y,z) → (x cosθ + y sinθ, y cosθ - x sinθ, z)
is lipschitz continuous, & add it
- feedback for copy/paste (flash screen or something)
-- clean up code w a big state object
- Params instead of depth for GenRandom
- allow multiple endpoints (cube & sphere & ...)
- save seeds to a file then let user go back&forth through past sdfs
@@ -169,65 +169,113 @@ fn get_rng() -> impl rand::Rng {
rand::rngs::SmallRng::seed_from_u64(rand::random::<u64>())
}
-fn try_main() -> Result<(), String> {
- let mut window = win::Window::new("AutoSDF", 1280, 720, true)
- .map_err(|e| format!("Error creating window: {e}"))?;
- let mut programs = Programs::new(&mut window);
- let config = sdf::SceneConfig {
- sdf_max_depth: 7,
- color_max_depth: 6,
- };
- let mut scene = sdf::Scene::good_random(&mut get_rng(), &config);
- programs.load_scene(&mut window, &scene).unwrap_or_else(|e|
- eprintln!("Error: {e}")
- );
- //gen_program_from_string(&mut window, &mut program, "a263736466a167436f6d706f736583a1695472616e736c61746583a163463332fa3ea4c00ca163463332fa3e85dc00a163463332fa3f2bbdaea167436f6d706f736583a166526f7461746583a163463332fa3f750dc2a163463332fa3f5a7f0ea163463332fa3f2df98ca1634d696e82a167436f6d706f736583a167436f6d706f736582a16353696ea163463332fa3f7cc2a0a167436f6d706f736582684964656e74697479684964656e74697479a166537068657265a163463332fa3f26f8f6684964656e74697479a167436f6d706f736583a166526f7461746583a163463332fa3f1bfed8a163463332fa3f1e1e30a163463332fa3eddc6b0a1634d697883a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3ea149ec684964656e74697479a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3f6b0018684964656e74697479a163463332fa3e60a8d8684964656e74697479684964656e74697479684964656e746974796e636f6c6f725f66756e6374696f6ea165537153696ea163463332fa3ebaa7ec")?;
-
- let mut buffer = window.create_buffer();
- let data: &[[f32; 2]] = &[
- [-1.0, -1.0],
- [1.0, -1.0],
- [1.0, 1.0],
- [-1.0, -1.0],
- [1.0, 1.0],
- [-1.0, 1.0],
- ];
- window.set_buffer_data(&mut buffer, data);
- let mut array = window.create_vertex_array(buffer, &programs.main);
- window.array_attrib2f(&mut array, "v_pos", 0);
-
- let mut view = View::default();
-
- window.set_mouse_relative(true);
-
- let mut frame_time = Instant::now();
- let mut show_debug_info = false;
- let mut total_time = 0.0;
-
- 'mainloop: loop {
- let frame_dt = frame_time.elapsed().as_secs_f32();
- frame_time = Instant::now();
+// sample size when testing to find default level set
+const TEST_HEIGHT: u16 = 100;
+const TEST_WIDTH: u16 = 100;
+
+struct State {
+ window: win::Window,
+ view: View,
+ show_debug_info: bool,
+ total_time: f64,
+ frame_time: Instant,
+ programs: Programs,
+ config: sdf::SceneConfig,
+ scene: sdf::Scene,
+ framebuffer_texture: win::Texture,
+ framebuffer: win::Framebuffer,
+ main_array: win::VertexArray,
+}
- while let Some(event) = window.next_event() {
+impl State {
+ fn new() -> Result<Self, String> {
+
+ let mut window = win::Window::new("AutoSDF", 1280, 720, true)
+ .map_err(|e| format!("Error creating window: {e}"))?;
+ let mut programs = Programs::new(&mut window);
+ let config = sdf::SceneConfig {
+ sdf_max_depth: 7,
+ color_max_depth: 6,
+ };
+ let scene = sdf::Scene::good_random(&mut get_rng(), &config);
+ programs.load_scene(&mut window, &scene).unwrap_or_else(|e|
+ eprintln!("Error: {e}")
+ );
+ //gen_program_from_string(&mut window, &mut program, "a263736466a167436f6d706f736583a1695472616e736c61746583a163463332fa3ea4c00ca163463332fa3e85dc00a163463332fa3f2bbdaea167436f6d706f736583a166526f7461746583a163463332fa3f750dc2a163463332fa3f5a7f0ea163463332fa3f2df98ca1634d696e82a167436f6d706f736583a167436f6d706f736582a16353696ea163463332fa3f7cc2a0a167436f6d706f736582684964656e74697479684964656e74697479a166537068657265a163463332fa3f26f8f6684964656e74697479a167436f6d706f736583a166526f7461746583a163463332fa3f1bfed8a163463332fa3f1e1e30a163463332fa3eddc6b0a1634d697883a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3ea149ec684964656e74697479a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3f6b0018684964656e74697479a163463332fa3e60a8d8684964656e74697479684964656e74697479684964656e746974796e636f6c6f725f66756e6374696f6ea165537153696ea163463332fa3ebaa7ec")?;
+
+ let mut framebuffer_texture = window.create_texture(&Default::default());
+ // we don't really care if there's an error. not much bad will happen.
+ let _ = window.set_texture_no_data::<win::ColorU8>(&mut framebuffer_texture, TEST_WIDTH.into(), TEST_HEIGHT.into());
+
+ let mut framebuffer = window.create_framebuffer();
+ window.set_framebuffer_texture(
+ &mut framebuffer,
+ win::FramebufferAttachment::Color0,
+ &framebuffer_texture,
+ );
+
+ let mut main_buffer = window.create_buffer();
+ let data: &[[f32; 2]] = &[
+ [-1.0, -1.0],
+ [1.0, -1.0],
+ [1.0, 1.0],
+ [-1.0, -1.0],
+ [1.0, 1.0],
+ [-1.0, 1.0],
+ ];
+ window.set_buffer_data(&mut main_buffer, data);
+ let mut main_array = window.create_vertex_array(main_buffer, &programs.main);
+ window.array_attrib2f(&mut main_array, "v_pos", 0);
+ let view = View::default();
+
+ window.set_mouse_relative(true);
+
+ Ok(Self {
+ window,
+ programs,
+ view,
+ config,
+ frame_time: Instant::now(),
+ show_debug_info: false,
+ total_time: 0.0,
+ scene,
+ framebuffer_texture,
+ framebuffer,
+ main_array,
+ })
+ }
+
+ fn load_scene(&mut self, scene: sdf::Scene) {
+ match self.programs.load_scene(&mut self.window, &scene) {
+ Ok(()) => {
+ self.scene = scene;
+ self.view.level_set = 0.0;
+ }
+ Err(e) => {
+ eprintln!("Error: {e}")
+ }
+ };
+ }
+
+ // returns false if we should quit
+ fn frame(&mut self) -> bool {
+ let frame_dt = self.frame_time.elapsed().as_secs_f32();
+ self.frame_time = Instant::now();
+ self.total_time += f64::from(frame_dt);
+
+ while let Some(event) = self.window.next_event() {
use win::Event::*;
use win::Key::*;
match event {
- Quit | KeyDown { key: Escape, .. } => break 'mainloop,
- KeyDown { key: F1, .. } => show_debug_info = !show_debug_info,
+ Quit | KeyDown { key: Escape, .. } => return false,
+ KeyDown { key: F1, .. } => self.show_debug_info = !self.show_debug_info,
KeyDown { key: R, .. } => {
- scene = sdf::Scene::good_random(&mut get_rng(), &config);
- match programs.load_scene(&mut window, &scene) {
- Ok(()) => {
- view.level_set = 0.0;
- }
- Err(e) => {
- eprintln!("Error: {e}")
- }
- };
+ let new_scene = sdf::Scene::good_random(&mut get_rng(), &self.config);
+ self.load_scene(new_scene);
}
KeyDown { key: C, modifier, .. } if modifier.ctrl() => {
// copy scene
- match window.set_clipboard_text(&scene.export_string()) {
+ match self.window.set_clipboard_text(&self.scene.export_string()) {
Ok(()) => {
}
Err(e) => {
@@ -237,19 +285,11 @@ fn try_main() -> Result<(), String> {
}
KeyDown { key: V, modifier, .. } if modifier.ctrl() => {
// paste scene
- match window.get_clipboard_text() {
+ match self.window.get_clipboard_text() {
Ok(s) => {
match sdf::Scene::import_string(&s) {
Some(new_scene) => {
- scene = new_scene;
- match programs.load_scene(&mut window, &scene) {
- Ok(()) => {
- view.level_set = 0.0;
- }
- Err(e) => {
- eprintln!("Error: {e}")
- }
- }
+ self.load_scene(new_scene);
}
None => {
eprintln!("bad string")
@@ -262,11 +302,11 @@ fn try_main() -> Result<(), String> {
}
}
}
- KeyDown { key: N0, .. } => view.level_set = 0.0,
+ KeyDown { key: N0, .. } => self.view.level_set = 0.0,
MouseMotion { xrel, yrel, .. } => {
let mouse_sensitivity = 0.05;
- view.yaw_by(-xrel as f32 * mouse_sensitivity * frame_dt);
- view.pitch_by(-yrel as f32 * mouse_sensitivity * frame_dt);
+ self.view.yaw_by(-xrel as f32 * mouse_sensitivity * frame_dt);
+ self.view.pitch_by(-yrel as f32 * mouse_sensitivity * frame_dt);
}
_ => {}
}
@@ -278,6 +318,7 @@ fn try_main() -> Result<(), String> {
let mut dy = 0.0;
let mut dz = 0.0;
let mut dl = 0.0;
+ let window = &self.window;
use win::Key::*;
if window.any_key_down(&[W, Up]) {
dz -= 1.0;
@@ -310,20 +351,22 @@ fn try_main() -> Result<(), String> {
if let Some(motion) = motion.try_normalize(0.001) {
let move_speed = 4.0 * speed_multiplier;
let motion = motion * frame_dt * move_speed;
- let motion = view.rotation() * motion;
- view.pos += motion;
+ let motion = self.view.rotation() * motion;
+ self.view.pos += motion;
}
let level_set_speed = 1.0 * speed_multiplier;
- view.level_set += dl * frame_dt * level_set_speed;
+ self.view.level_set += dl * frame_dt * level_set_speed;
}
+ let window = &mut self.window;
+ let view = &self.view;
window.viewport_full_screen();
window.clear_screen(win::ColorF32::BLACK);
- window.use_program(&programs.main);
+ window.use_program(&self.programs.main);
window.uniform1f("u_aspect_ratio", window.aspect_ratio());
- window.uniform1f("u_time", total_time);
+ window.uniform1f("u_time", self.total_time as f32);
window.uniform1f("u_fov", std::f32::consts::PI * 0.25);
window.uniform1f("u_focal_length", 1.0);
window.uniform1f("u_level_set", view.level_set);
@@ -331,15 +374,21 @@ fn try_main() -> Result<(), String> {
window.uniform3x3f("u_rotation", view.rotation().as_slice());
window.uniform3f_slice("u_translation", view.pos.as_slice());
- window.draw_array(&array);
+ window.draw_array(&self.main_array);
window.swap();
- if show_debug_info {
+ if self.show_debug_info {
println!("frame time = {:?}ms", frame_dt * 1000.0);
}
-
- total_time += frame_dt;
+
+ true
}
+}
+
+
+fn try_main() -> Result<(), String> {
+ let mut state = State::new()?;
+ while state.frame() {}
Ok(())
}
diff --git a/src/win.rs b/src/win.rs
index a9b277e..0e0fcbd 100644
--- a/src/win.rs
+++ b/src/win.rs
@@ -790,7 +790,7 @@ impl Texture {
unsafe fn set_data<T: Color>(
&mut self,
- data: &[T],
+ data: Option<&[T]>,
width: usize,
height: usize,
) -> Result<(), String> {
@@ -799,13 +799,22 @@ impl Texture {
let width: GLsizei = width.try_into().map_err(|_| "width too large")?;
let height: GLsizei = height.try_into().map_err(|_| "height too large")?;
let expected_len = width * height;
- if data.len() as GLsizei != expected_len {
- return Err(format!(
- "bad data length (expected {}, got {})",
- expected_len,
- data.len()
- ));
- }
+
+
+ let ptr = match data {
+ Some(data) => {
+ if data.len() as GLsizei != expected_len {
+ return Err(format!(
+ "bad data length (expected {}, got {})",
+ expected_len,
+ data.len()
+ ));
+ }
+ data.as_ptr()
+ },
+ None => std::ptr::null()
+ };
+
let params = &self.params;
self.bind();
gl::TexImage2D(
@@ -817,7 +826,7 @@ impl Texture {
0,
T::GL_FORMAT,
T::GL_TYPE,
- data.as_ptr() as _,
+ ptr.cast(),
);
gl::TexParameteri(
gl::TEXTURE_2D,
@@ -948,11 +957,11 @@ impl Framebuffer {
}
unsafe fn bind(&self) {
- gl::BindTexture(gl::FRAMEBUFFER, self.id);
+ gl::BindFramebuffer(gl::FRAMEBUFFER, self.id);
}
unsafe fn unbind() {
- gl::BindTexture(gl::FRAMEBUFFER, 0);
+ gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
}
unsafe fn set_texture(&mut self, attachment: FramebufferAttachment, texture: &Texture) {
@@ -1032,6 +1041,18 @@ impl Window {
audio_data: None,
})
}
+
+ pub fn set_vsync(&mut self, vsync: bool) {
+ unsafe {
+ sdl::gl_set_swap_interval(
+ if vsync {
+ 1
+ } else {
+ 0
+ }
+ );
+ }
+ }
pub fn show(&mut self) {
unsafe { sdl::show_window(self.sdlwin) };
@@ -1186,18 +1207,32 @@ impl Window {
}
}
- pub fn create_rgba_texture(&mut self, params: &TextureParams) -> Texture {
+ pub fn create_texture(&mut self, params: &TextureParams) -> Texture {
unsafe { Texture::new(params) }
}
- pub fn set_texture_data(
+ pub fn set_texture_data<T: Color>(
+ &mut self,
+ texture: &mut Texture,
+ data: &[T],
+ width: usize,
+ height: usize,
+ ) -> Result<(), String> {
+ unsafe { texture.set_data(Some(data), width, height) }?;
+ Ok(())
+ }
+
+ /// sets texture width + height but not data.
+ ///
+ /// NOTE: you must still specify the color type!
+ /// for framebuffers, etc.
+ pub fn set_texture_no_data<T: Color>(
&mut self,
texture: &mut Texture,
- data: &[impl Color],
width: usize,
height: usize,
) -> Result<(), String> {
- unsafe { texture.set_data(data, width, height) }?;
+ unsafe { texture.set_data::<T>(None, width, height) }?;
Ok(())
}
@@ -1383,24 +1418,24 @@ impl Window {
unsafe { array.draw() };
}
- pub fn is_key_down(&mut self, key: Key) -> bool {
+ pub fn is_key_down(&self, key: Key) -> bool {
let kbd_state = unsafe { sdl::get_keyboard_state() };
kbd_state[key.to_sdl() as usize] != 0
}
- pub fn any_key_down(&mut self, keys: &[Key]) -> bool {
+ pub fn any_key_down(&self, keys: &[Key]) -> bool {
keys.iter().any(|&k| self.is_key_down(k))
}
- pub fn is_shift_down(&mut self) -> bool {
+ pub fn is_shift_down(&self) -> bool {
self.is_key_down(Key::LShift) || self.is_key_down(Key::RShift)
}
- pub fn is_ctrl_down(&mut self) -> bool {
+ pub fn is_ctrl_down(&self) -> bool {
self.is_key_down(Key::LCtrl) || self.is_key_down(Key::RCtrl)
}
- pub fn is_alt_down(&mut self) -> bool {
+ pub fn is_alt_down(&self) -> bool {
self.is_key_down(Key::LAlt) || self.is_key_down(Key::RAlt)
}