Kinda working
This commit is contained in:
850
Cargo.lock
generated
850
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,9 @@ anyhow = "1.0.100"
|
||||
bytemuck = "1.24.0"
|
||||
cgmath = "0.18.0"
|
||||
crevice = {version = "0.18.0", features = ["cgmath"]}
|
||||
egui = "0.33.3"
|
||||
egui-wgpu = "0.33.3"
|
||||
egui-winit = "0.33.3"
|
||||
env_logger = "0.11.8"
|
||||
pollster = "0.4.0"
|
||||
wgpu = "27.0.1"
|
||||
|
||||
@ -1,14 +1,20 @@
|
||||
struct FractalParameters
|
||||
{
|
||||
translation: vec3<f32>,
|
||||
rotation: vec3<f32>,
|
||||
scale: f32,
|
||||
iterations: u32
|
||||
}
|
||||
|
||||
struct RayMarchingPushConstants
|
||||
{
|
||||
inverse_proj: mat4x4<f32>,
|
||||
view_matrix: mat4x4<f32>,
|
||||
camera_pos: vec3<f32>,
|
||||
|
||||
scale: f32,
|
||||
translation: vec3<f32>,
|
||||
rotation: vec3<f32>,
|
||||
fractal_parameters: FractalParameters
|
||||
}
|
||||
|
||||
|
||||
var<push_constant> constants: RayMarchingPushConstants;
|
||||
|
||||
struct Vertex
|
||||
@ -92,31 +98,39 @@ fn sdf(pos: vec3<f32>) -> f32
|
||||
var x = pos;
|
||||
var t = 1.;
|
||||
|
||||
for(var i = 0u; i < 3; i++)
|
||||
for(var i = 0u; i < constants.fractal_parameters.iterations; i++)
|
||||
{
|
||||
x *= 1.5;
|
||||
t *= 1.5;
|
||||
x *= constants.fractal_parameters.scale;
|
||||
t *= constants.fractal_parameters.scale;
|
||||
x = abs(x);
|
||||
x += vec3<f32>(0.01, 0.02, 0.08);
|
||||
x += constants.fractal_parameters.translation;
|
||||
x *= rot();
|
||||
}
|
||||
|
||||
return sdf_box(x, vec3<f32>(1.)) / t;
|
||||
return sdf_octahedron(x, 1.) / t;
|
||||
}
|
||||
|
||||
fn rot() -> mat3x3<f32>
|
||||
{
|
||||
let rx = 0.6;
|
||||
let ry = 8.1;
|
||||
let rx = constants.fractal_parameters.rotation.x;
|
||||
let ry = constants.fractal_parameters.rotation.y;
|
||||
let rz = constants.fractal_parameters.rotation.z;
|
||||
return mat3x3<f32>(
|
||||
cos(rx), sin(rx), 0.,
|
||||
-sin(rx), cos(rx), 0.,
|
||||
0., 0., 1.
|
||||
)*
|
||||
)
|
||||
*
|
||||
mat3x3<f32>(
|
||||
cos(ry), 0., sin(ry),
|
||||
0., 1., 0.,
|
||||
-sin(ry), 0., cos(ry)
|
||||
)
|
||||
*
|
||||
mat3x3<f32>(
|
||||
1., 0., 0.,
|
||||
0., cos(ry), sin(ry),
|
||||
0, -sin(ry), cos(ry)
|
||||
0., cos(rz), sin(rz),
|
||||
0, -sin(rz), cos(rz)
|
||||
);
|
||||
|
||||
}
|
||||
@ -127,9 +141,15 @@ fn sdf_box(pos: vec3<f32>, b: vec3<f32>) -> f32
|
||||
return length(max(q, vec3<f32>(0.))) + min(max(q.x, max(q.y, q.z)), 0.);
|
||||
}
|
||||
|
||||
fn sdf_octahedron(pos: vec3<f32>, s: f32) -> f32
|
||||
{
|
||||
let p = abs(pos);
|
||||
return (p.x + p.y + p.z - s) *0.57735;
|
||||
}
|
||||
|
||||
fn sdf_gradient(p: vec3<f32>) -> vec3<f32>
|
||||
{
|
||||
let eps = 0.000001;
|
||||
let eps = 0.0001;
|
||||
let h = vec2<f32>(eps, 0);
|
||||
|
||||
return normalize(
|
||||
|
||||
137
src/egui_renderer.rs
Normal file
137
src/egui_renderer.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use egui::{Context, PaintCallbackInfo};
|
||||
use egui_wgpu::{CallbackResources, CallbackTrait, Renderer, RendererOptions, ScreenDescriptor};
|
||||
use egui_winit::State;
|
||||
use wgpu::{CommandEncoder, Device, Queue, RenderPass, TextureFormat, TextureView};
|
||||
use winit::{event::WindowEvent, window::Window};
|
||||
|
||||
pub struct EguiState {
|
||||
pub state: State,
|
||||
pub renderer: Renderer,
|
||||
pub frame_started: bool,
|
||||
//pub msaa_texture: TextureView,
|
||||
pub color_format: TextureFormat,
|
||||
}
|
||||
|
||||
impl EguiState {
|
||||
pub fn context(&self) -> &Context {
|
||||
self.state.egui_ctx()
|
||||
}
|
||||
|
||||
pub fn new(device: &Device, output_color_format: TextureFormat, window: &Window) -> EguiState {
|
||||
let egui_context = Context::default();
|
||||
|
||||
let egui_state = egui_winit::State::new(
|
||||
egui_context,
|
||||
egui::ViewportId::ROOT,
|
||||
&window,
|
||||
Some(window.scale_factor() as f32),
|
||||
None,
|
||||
Some(2 * 1024),
|
||||
);
|
||||
|
||||
let options = RendererOptions {
|
||||
//msaa_samples: SAMPLE_COUNT,
|
||||
//depth_stencil_format: Some(TextureFormat::Depth24PlusStencil8),
|
||||
..Default::default()
|
||||
};
|
||||
let egui_renderer = Renderer::new(device, output_color_format, options);
|
||||
|
||||
EguiState {
|
||||
state: egui_state,
|
||||
renderer: egui_renderer,
|
||||
frame_started: false,
|
||||
color_format: output_color_format,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, _device: &Device, _width: u32, _height: u32) {}
|
||||
|
||||
pub fn handle_event(&mut self, window: &Window, event: &WindowEvent) {
|
||||
let _ = self.state.on_window_event(window, event);
|
||||
}
|
||||
|
||||
pub fn begin_frame(&mut self, window: &Window) {
|
||||
let input = self.state.take_egui_input(window);
|
||||
self.state.egui_ctx().begin_pass(input);
|
||||
self.frame_started = true;
|
||||
}
|
||||
|
||||
pub fn end_frame_and_draw(
|
||||
&mut self,
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
encoder: &mut CommandEncoder,
|
||||
window: &Window,
|
||||
window_surface_view: &TextureView,
|
||||
screen_descriptor: ScreenDescriptor,
|
||||
) {
|
||||
if !self.frame_started {
|
||||
panic!("begin_frame must be called before end_frame_and_draw can be called!");
|
||||
}
|
||||
|
||||
//self.ppp(screen_descriptor.pixels_per_point);
|
||||
|
||||
let full_output = self.state.egui_ctx().end_pass();
|
||||
|
||||
self.state
|
||||
.handle_platform_output(window, full_output.platform_output);
|
||||
|
||||
let tris = self
|
||||
.state
|
||||
.egui_ctx()
|
||||
.tessellate(full_output.shapes, self.state.egui_ctx().pixels_per_point());
|
||||
for (id, image_delta) in &full_output.textures_delta.set {
|
||||
self.renderer
|
||||
.update_texture(device, queue, *id, image_delta);
|
||||
}
|
||||
self.renderer
|
||||
.update_buffers(device, queue, encoder, &tris, &screen_descriptor);
|
||||
let rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
view: window_surface_view,
|
||||
resolve_target: None,
|
||||
ops: egui_wgpu::wgpu::Operations {
|
||||
load: egui_wgpu::wgpu::LoadOp::Load,
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
depth_slice: None,
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
label: Some("egui main render pass"),
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
|
||||
self.renderer
|
||||
.render(&mut rpass.forget_lifetime(), &tris, &screen_descriptor);
|
||||
for x in &full_output.textures_delta.free {
|
||||
self.renderer.free_texture(x)
|
||||
}
|
||||
|
||||
self.frame_started = false;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CallbackFn<P>
|
||||
where
|
||||
P: Fn(PaintCallbackInfo, &mut RenderPass<'static>, &CallbackResources),
|
||||
{
|
||||
//pub : FnOnce(&Device, &Queue, &ScreenDescriptor, &mut CommandEncoder, &mut CallbackResources) -> Vec<>
|
||||
pub paint_fn: P,
|
||||
}
|
||||
|
||||
impl<P> CallbackTrait for CallbackFn<P>
|
||||
where
|
||||
P: Fn(PaintCallbackInfo, &mut RenderPass<'static>, &CallbackResources)
|
||||
+ std::marker::Sync
|
||||
+ std::marker::Send,
|
||||
{
|
||||
fn paint(
|
||||
&self,
|
||||
info: egui::PaintCallbackInfo,
|
||||
render_pass: &mut wgpu::RenderPass<'static>,
|
||||
callback_resources: &egui_wgpu::CallbackResources,
|
||||
) {
|
||||
(self.paint_fn)(info, render_pass, callback_resources)
|
||||
}
|
||||
}
|
||||
11
src/lib.rs
11
src/lib.rs
@ -1,14 +1,12 @@
|
||||
pub mod egui_renderer;
|
||||
pub mod state;
|
||||
|
||||
use std::{os::linux::raw::stat, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
use winit::{
|
||||
application::ApplicationHandler,
|
||||
dpi::{LogicalPosition, PhysicalPosition},
|
||||
event::{KeyEvent, RawKeyEvent, WindowEvent},
|
||||
event::WindowEvent,
|
||||
event_loop::{self, EventLoop},
|
||||
keyboard::{Key, KeyCode, PhysicalKey},
|
||||
platform::modifier_supplement::KeyEventExtModifierSupplement,
|
||||
window::Window,
|
||||
};
|
||||
|
||||
@ -57,10 +55,11 @@ impl ApplicationHandler for RustSponges {
|
||||
fn window_event(
|
||||
&mut self,
|
||||
event_loop: &event_loop::ActiveEventLoop,
|
||||
window_id: winit::window::WindowId,
|
||||
_window_id: winit::window::WindowId,
|
||||
event: winit::event::WindowEvent,
|
||||
) {
|
||||
let state = self.state.as_mut().unwrap();
|
||||
state.handle_event(&event);
|
||||
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
|
||||
104
src/state.rs
104
src/state.rs
@ -1,19 +1,21 @@
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use cgmath::{Deg, Matrix4, SquareMatrix, Vector3};
|
||||
use cgmath::{Matrix4, SquareMatrix, Vector3};
|
||||
use crevice::std430::AsStd430;
|
||||
use egui_wgpu::ScreenDescriptor;
|
||||
use wgpu::{
|
||||
ColorWrites, Features, FeaturesWGPU, FeaturesWebGPU, FragmentState, PipelineLayoutDescriptor,
|
||||
PushConstantRange, RenderPipeline, RenderPipelineDescriptor, ShaderStages, VertexState,
|
||||
include_wgsl,
|
||||
};
|
||||
use winit::{
|
||||
dpi::PhysicalPosition,
|
||||
event::{ElementState, KeyEvent, MouseButton, RawKeyEvent},
|
||||
event::{ElementState, KeyEvent, MouseButton, WindowEvent},
|
||||
keyboard::{KeyCode, PhysicalKey},
|
||||
window::Window,
|
||||
};
|
||||
|
||||
use crate::egui_renderer::EguiState;
|
||||
|
||||
pub struct State {
|
||||
window: Arc<Window>,
|
||||
device: wgpu::Device,
|
||||
@ -21,16 +23,20 @@ pub struct State {
|
||||
size: winit::dpi::PhysicalSize<u32>,
|
||||
surface: wgpu::Surface<'static>,
|
||||
surface_format: wgpu::TextureFormat,
|
||||
egui_state: EguiState,
|
||||
|
||||
// World
|
||||
camera: Camera,
|
||||
fractal_parameters: FractalParameters,
|
||||
|
||||
// Raymarching
|
||||
ray_marching_renderer: RenderPipeline,
|
||||
|
||||
// Controls
|
||||
pressed_set: HashSet<KeyCode>,
|
||||
|
||||
mouse_inside: bool,
|
||||
mouse_over_gui: bool,
|
||||
}
|
||||
|
||||
pub struct Camera {
|
||||
@ -44,6 +50,14 @@ pub struct Camera {
|
||||
zfar: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, AsStd430)]
|
||||
pub struct FractalParameters {
|
||||
translation: Vector3<f32>,
|
||||
rotation: Vector3<f32>,
|
||||
scale: f32,
|
||||
iteations: u32,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
fn get_proj(&self) -> Matrix4<f32> {
|
||||
cgmath::perspective(cgmath::Deg(self.fovy), self.aspect, self.znear, self.zfar)
|
||||
@ -126,6 +140,8 @@ impl State {
|
||||
});
|
||||
|
||||
let state = State {
|
||||
egui_state: EguiState::new(&device, surface_format, &window),
|
||||
|
||||
window,
|
||||
device,
|
||||
queue,
|
||||
@ -142,10 +158,18 @@ impl State {
|
||||
znear: 0.001,
|
||||
zfar: 1000.,
|
||||
},
|
||||
fractal_parameters: FractalParameters {
|
||||
translation: Vector3::new(0., 0., 0.),
|
||||
rotation: Vector3::new(0., 0., 0.),
|
||||
scale: 1.,
|
||||
iteations: 1,
|
||||
},
|
||||
|
||||
ray_marching_renderer,
|
||||
|
||||
pressed_set: HashSet::new(),
|
||||
mouse_inside: false,
|
||||
mouse_over_gui: false,
|
||||
};
|
||||
|
||||
// Configure surface for the first time
|
||||
@ -181,6 +205,10 @@ impl State {
|
||||
self.configure_surface();
|
||||
}
|
||||
|
||||
pub fn handle_event(&mut self, event: &WindowEvent) {
|
||||
self.egui_state.handle_event(&self.window, event);
|
||||
}
|
||||
|
||||
pub fn render(&mut self) {
|
||||
self.handle_movement();
|
||||
// Create texture view
|
||||
@ -225,6 +253,7 @@ impl State {
|
||||
inverse_projection_matrix: self.camera.get_proj().invert().unwrap(),
|
||||
camera_pos: self.camera.position,
|
||||
view_matrix: self.camera.get_view(),
|
||||
fractal_parameters: self.fractal_parameters,
|
||||
}
|
||||
.as_std430()
|
||||
.as_bytes(),
|
||||
@ -233,6 +262,72 @@ impl State {
|
||||
|
||||
// End the renderpass.
|
||||
drop(renderpass);
|
||||
// Egui
|
||||
{
|
||||
let screen_descriptor = ScreenDescriptor {
|
||||
size_in_pixels: [self.size.width, self.size.height],
|
||||
pixels_per_point: 1.,
|
||||
};
|
||||
self.egui_state.begin_frame(&self.window);
|
||||
|
||||
egui::Window::new("Controls")
|
||||
.resizable(true)
|
||||
.show(self.egui_state.context(), |ui| {
|
||||
ui.label("Translation");
|
||||
ui.add(
|
||||
egui::Slider::new(&mut self.fractal_parameters.translation.x, -0.9..=0.9)
|
||||
.text("X"),
|
||||
);
|
||||
ui.add(
|
||||
egui::Slider::new(&mut self.fractal_parameters.translation.y, -0.9..=0.9)
|
||||
.text("Y"),
|
||||
);
|
||||
ui.add(
|
||||
egui::Slider::new(&mut self.fractal_parameters.translation.z, -0.9..=0.9)
|
||||
.text("Z"),
|
||||
);
|
||||
|
||||
ui.add_space(6.);
|
||||
ui.label("Rotation");
|
||||
ui.add(
|
||||
egui::Slider::new(&mut self.fractal_parameters.rotation.x, -1.9..=1.9)
|
||||
.text("X"),
|
||||
);
|
||||
ui.add(
|
||||
egui::Slider::new(&mut self.fractal_parameters.rotation.y, -1.9..=1.9)
|
||||
.text("Y"),
|
||||
);
|
||||
ui.add(
|
||||
egui::Slider::new(&mut self.fractal_parameters.rotation.z, -1.9..=1.9)
|
||||
.text("Z"),
|
||||
);
|
||||
|
||||
ui.add_space(6.);
|
||||
ui.label("Scale");
|
||||
ui.add(
|
||||
egui::Slider::new(&mut self.fractal_parameters.scale, 1.0..=2.)
|
||||
.text("scale"),
|
||||
);
|
||||
|
||||
ui.add_space(6.);
|
||||
ui.label("Iterations");
|
||||
ui.add(
|
||||
egui::Slider::new(&mut self.fractal_parameters.iteations, 0..=30)
|
||||
.text("iteations"),
|
||||
);
|
||||
});
|
||||
|
||||
self.mouse_over_gui = self.egui_state.context().is_pointer_over_area();
|
||||
|
||||
self.egui_state.end_frame_and_draw(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
&mut encoder,
|
||||
&self.window,
|
||||
&texture_view,
|
||||
screen_descriptor,
|
||||
);
|
||||
}
|
||||
|
||||
// Submit the command in the queue to execute
|
||||
self.queue.submit([encoder.finish()]);
|
||||
@ -272,7 +367,7 @@ impl State {
|
||||
}
|
||||
|
||||
pub fn mouse_event(&mut self, state: ElementState, button: MouseButton) {
|
||||
if state == ElementState::Pressed && button == MouseButton::Left {
|
||||
if state == ElementState::Pressed && button == MouseButton::Left && !self.mouse_over_gui {
|
||||
self.mouse_inside = true;
|
||||
self.window.set_cursor_visible(false);
|
||||
self.window
|
||||
@ -316,4 +411,5 @@ pub struct RayMarchingPushConstants {
|
||||
inverse_projection_matrix: Matrix4<f32>,
|
||||
view_matrix: Matrix4<f32>,
|
||||
camera_pos: Vector3<f32>,
|
||||
fractal_parameters: FractalParameters,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user