Compare commits
No commits in common. "8736db19a36e43040560854b88608955da33116a" and "df2134a8a5d56cb179ef3639f4567fe2eb640cca" have entirely different histories.
8736db19a3
...
df2134a8a5
865
Cargo.lock
generated
865
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
|
|
@ -21,11 +21,8 @@ show-image = "0.14.0"
|
|||
flo_draw = "0.3.1"
|
||||
flo_canvas = "0.3.1"
|
||||
itertools-num = "0.1.3"
|
||||
winit = "0.29"
|
||||
itertools = "0.13.0"
|
||||
wgpu = "22.1.0"
|
||||
bytemuck = { version = "1.18.0", features = ["derive"] }
|
||||
pollster = "0.3.0"
|
||||
glium = "0.35.0"
|
||||
winit = "0.30.5"
|
||||
|
||||
[dev-dependencies]
|
||||
approx = "0.5.1"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
use std::{iter, mem, time::Instant};
|
||||
use std::time::Instant;
|
||||
|
||||
use glam::{mat4, vec2, vec3, vec4, Mat4, Vec3};
|
||||
use wgpu::{util::DeviceExt, ShaderStages};
|
||||
use glium::{
|
||||
backend::{glutin::SimpleWindowBuilder, Facade},
|
||||
glutin::config::ConfigTemplateBuilder,
|
||||
implement_vertex,
|
||||
index::PrimitiveType,
|
||||
uniform,
|
||||
winit::event::{Event, WindowEvent},
|
||||
DrawParameters, Program, Surface, VertexBuffer,
|
||||
};
|
||||
use winit::{
|
||||
event::*,
|
||||
event_loop::EventLoop,
|
||||
keyboard::{KeyCode, PhysicalKey},
|
||||
window::{Window, WindowBuilder},
|
||||
};
|
||||
|
||||
mod scene;
|
||||
|
|
@ -16,42 +22,29 @@ mod scene;
|
|||
// * Y: left
|
||||
// * Z: up
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct Vertex {
|
||||
position: [f32; 3],
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
fn desc() -> wgpu::VertexBufferLayout<'static> {
|
||||
use std::mem;
|
||||
wgpu::VertexBufferLayout {
|
||||
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &[wgpu::VertexAttribute {
|
||||
offset: mem::offset_of!(Self, position) as u64,
|
||||
shader_location: 0,
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
}],
|
||||
}
|
||||
}
|
||||
}
|
||||
implement_vertex!(Vertex, position);
|
||||
|
||||
struct Wireframe {
|
||||
color: Vec3,
|
||||
data: wgpu::Buffer,
|
||||
size: u32,
|
||||
mode: PrimitiveType,
|
||||
data: VertexBuffer<Vertex>,
|
||||
}
|
||||
|
||||
fn prepare_scene(device: &wgpu::Device) -> Vec<Wireframe> {
|
||||
fn prepare_scene(display: &impl Facade) -> Vec<Wireframe> {
|
||||
scene::build()
|
||||
.into_iter()
|
||||
.map(|line| {
|
||||
let color = line.color;
|
||||
let mode;
|
||||
let data: Vec<Vertex>;
|
||||
match line.line {
|
||||
scene::Line::Lines(_) => todo!(),
|
||||
scene::Line::Strip(pts) => {
|
||||
mode = PrimitiveType::LineStrip;
|
||||
data = pts
|
||||
.into_iter()
|
||||
.map(|p| Vertex {
|
||||
|
|
@ -60,23 +53,17 @@ fn prepare_scene(device: &wgpu::Device) -> Vec<Wireframe> {
|
|||
.collect();
|
||||
}
|
||||
scene::Line::Loop(pts) => {
|
||||
let first = pts.first().copied();
|
||||
mode = PrimitiveType::LineLoop;
|
||||
data = pts
|
||||
.into_iter()
|
||||
.chain(first)
|
||||
.map(|p| Vertex {
|
||||
position: p.to_array(),
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
};
|
||||
let size = data.len() as u32;
|
||||
let data = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Vertex Buffer"),
|
||||
contents: bytemuck::cast_slice(&data),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
});
|
||||
Wireframe { color, data, size }
|
||||
let data = VertexBuffer::new(display, &data).unwrap();
|
||||
Wireframe { color, mode, data }
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
@ -168,367 +155,111 @@ static KEYS_ROTATE: &'static [(PhysicalKey, Vec3)] = &[
|
|||
(PhysicalKey::Code(KeyCode::Numpad6), vec3(0., 0., -1.)),
|
||||
];
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
struct CameraUniform {
|
||||
mvp: [[f32; 4]; 4],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
struct LineUniform {
|
||||
color: [f32; 3],
|
||||
_pad: f32,
|
||||
}
|
||||
|
||||
struct State<'a> {
|
||||
surface: wgpu::Surface<'a>,
|
||||
device: wgpu::Device,
|
||||
queue: wgpu::Queue,
|
||||
config: wgpu::SurfaceConfiguration,
|
||||
size: winit::dpi::PhysicalSize<u32>,
|
||||
render_pipeline: wgpu::RenderPipeline,
|
||||
|
||||
kbd: keyctl::Keyboard,
|
||||
cam: camctl::CameraLocation,
|
||||
t1: Instant,
|
||||
|
||||
camera_uniform: CameraUniform,
|
||||
camera_buffer: wgpu::Buffer,
|
||||
camera_bind_group: wgpu::BindGroup,
|
||||
|
||||
scene: Vec<Wireframe>,
|
||||
|
||||
window: &'a Window,
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
async fn new(window: &'a Window) -> State<'a> {
|
||||
let size = window.inner_size();
|
||||
|
||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||
backends: wgpu::Backends::PRIMARY,
|
||||
..Default::default()
|
||||
});
|
||||
let surface = instance.create_surface(window).unwrap();
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::default(),
|
||||
compatible_surface: Some(&surface),
|
||||
force_fallback_adapter: false,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let (device, queue) = adapter
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: None,
|
||||
required_features: wgpu::Features::PUSH_CONSTANTS,
|
||||
required_limits: wgpu::Limits {
|
||||
max_push_constant_size: mem::size_of::<LineUniform>() as u32,
|
||||
..wgpu::Limits::default()
|
||||
},
|
||||
memory_hints: Default::default(),
|
||||
},
|
||||
None, // Trace path
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let surface_caps = surface.get_capabilities(&adapter);
|
||||
let surface_format = surface_caps
|
||||
.formats
|
||||
.iter()
|
||||
.copied()
|
||||
.find(|f| !f.is_srgb())
|
||||
.unwrap_or(surface_caps.formats[0]);
|
||||
let config = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: surface_format,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
present_mode: surface_caps.present_modes[0],
|
||||
alpha_mode: surface_caps.alpha_modes[0],
|
||||
view_formats: vec![],
|
||||
desired_maximum_frame_latency: 2,
|
||||
};
|
||||
|
||||
let kbd = keyctl::Keyboard::new();
|
||||
let cam = camctl::CameraLocation::new();
|
||||
let t1 = Instant::now();
|
||||
|
||||
let camera_uniform = CameraUniform {
|
||||
mvp: cam.view_mtx().to_cols_array_2d(),
|
||||
};
|
||||
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Camera Buffer"),
|
||||
contents: bytemuck::cast_slice(&[camera_uniform]),
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
let camera_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("camera_bind_group_layout"),
|
||||
});
|
||||
let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &camera_bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: camera_buffer.as_entire_binding(),
|
||||
}],
|
||||
label: Some("camera_bind_group"),
|
||||
});
|
||||
|
||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Shader"),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("ray.wgsl").into()),
|
||||
});
|
||||
|
||||
let line_push_constant_range = wgpu::PushConstantRange {
|
||||
stages: ShaderStages::VERTEX,
|
||||
range: 0..mem::size_of::<LineUniform>() as u32,
|
||||
};
|
||||
|
||||
let render_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Render Pipeline Layout"),
|
||||
bind_group_layouts: &[&camera_bind_group_layout],
|
||||
push_constant_ranges: &[line_push_constant_range],
|
||||
});
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render Pipeline"),
|
||||
layout: Some(&render_pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: "vs_main",
|
||||
buffers: &[Vertex::desc()],
|
||||
compilation_options: Default::default(),
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: config.format,
|
||||
blend: Some(wgpu::BlendState {
|
||||
color: wgpu::BlendComponent::OVER,
|
||||
alpha: wgpu::BlendComponent::OVER,
|
||||
}),
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
compilation_options: Default::default(),
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::LineStrip,
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
multiview: None,
|
||||
cache: None,
|
||||
});
|
||||
|
||||
let scene = prepare_scene(&device);
|
||||
|
||||
Self {
|
||||
surface,
|
||||
device,
|
||||
queue,
|
||||
config,
|
||||
size,
|
||||
render_pipeline,
|
||||
kbd,
|
||||
cam,
|
||||
t1,
|
||||
scene,
|
||||
camera_buffer,
|
||||
camera_bind_group,
|
||||
camera_uniform,
|
||||
window,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window(&self) -> &Window {
|
||||
&self.window
|
||||
}
|
||||
|
||||
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
if new_size.width > 0 && new_size.height > 0 {
|
||||
self.size = new_size;
|
||||
self.config.width = new_size.width;
|
||||
self.config.height = new_size.height;
|
||||
self.surface.configure(&self.device, &self.config);
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self) {
|
||||
let dt = {
|
||||
let t2 = Instant::now();
|
||||
let dt = t2 - self.t1;
|
||||
self.t1 = t2;
|
||||
dt.as_secs_f32()
|
||||
};
|
||||
self.cam.move_rel(100. * dt * self.kbd.control(&KEYS_MOVE));
|
||||
self.cam
|
||||
.rotate_rel_ypr(2. * dt * self.kbd.control(&KEYS_ROTATE));
|
||||
|
||||
let size = vec2(self.config.width as f32, self.config.height as f32);
|
||||
let size = size.normalize() * std::f32::consts::SQRT_2;
|
||||
let proj = make_proj_matrix(vec3(size.x, size.y, 2.), (1., 4096.));
|
||||
|
||||
let my_to_gl = mat4(
|
||||
vec4(0., 0., 1., 0.),
|
||||
vec4(-1., 0., 0., 0.),
|
||||
vec4(0., 1., 0., 0.),
|
||||
vec4(0., 0., 0., 1.),
|
||||
);
|
||||
let view = my_to_gl * self.cam.view_mtx();
|
||||
let mvp = proj * view;
|
||||
self.camera_uniform.mvp = mvp.to_cols_array_2d();
|
||||
self.queue.write_buffer(
|
||||
&self.camera_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[self.camera_uniform]),
|
||||
);
|
||||
}
|
||||
|
||||
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
||||
let output = self.surface.get_current_texture()?;
|
||||
let view = output
|
||||
.texture
|
||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
let mut encoder = self
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("Render Encoder"),
|
||||
});
|
||||
|
||||
{
|
||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("Render Pass"),
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
view: &view,
|
||||
resolve_target: None,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
||||
r: 0.,
|
||||
g: 0.,
|
||||
b: 0.,
|
||||
a: 1.,
|
||||
}),
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
occlusion_query_set: None,
|
||||
timestamp_writes: None,
|
||||
});
|
||||
|
||||
render_pass.set_pipeline(&self.render_pipeline);
|
||||
render_pass.set_bind_group(0, &self.camera_bind_group, &[]);
|
||||
for wireframe in &self.scene {
|
||||
let line = LineUniform {
|
||||
color: wireframe.color.to_array(),
|
||||
_pad: 0.,
|
||||
};
|
||||
render_pass.set_push_constants(ShaderStages::VERTEX, 0, bytemuck::bytes_of(&line));
|
||||
render_pass.set_vertex_buffer(0, wireframe.data.slice(..));
|
||||
render_pass.draw(0..wireframe.size, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
self.queue.submit(iter::once(encoder.finish()));
|
||||
output.present();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run() {
|
||||
let event_loop = EventLoop::new().unwrap();
|
||||
let window = WindowBuilder::new()
|
||||
fn main() {
|
||||
let event_loop = EventLoop::builder().build().unwrap();
|
||||
let cfg = ConfigTemplateBuilder::new().with_multisampling(8);
|
||||
let (window, display) = SimpleWindowBuilder::new()
|
||||
.with_config_template_builder(cfg)
|
||||
.with_title("Refraction: Wireframe")
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
.build(&event_loop);
|
||||
|
||||
// State::new uses async code, so we're going to wait for it to finish
|
||||
let mut state = State::new(&window).await;
|
||||
let mut surface_configured = false;
|
||||
let vs_src = include_str!("ray.v.glsl");
|
||||
let fs_src = include_str!("ray.f.glsl");
|
||||
let program = Program::from_source(&display, vs_src, fs_src, None).unwrap();
|
||||
|
||||
let scene = prepare_scene(&display);
|
||||
|
||||
let mut kbd = keyctl::Keyboard::new();
|
||||
let mut cam = camctl::CameraLocation::new();
|
||||
let mut t1 = Instant::now();
|
||||
|
||||
#[allow(deprecated)]
|
||||
event_loop
|
||||
.run(move |event, control_flow| {
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
ref event,
|
||||
window_id,
|
||||
} if window_id == state.window().id() => {
|
||||
match event {
|
||||
WindowEvent::KeyboardInput {
|
||||
device_id: _,
|
||||
event,
|
||||
is_synthetic: _,
|
||||
} => {
|
||||
state.kbd.set_key_state(event.physical_key, event.state);
|
||||
}
|
||||
WindowEvent::CloseRequested => control_flow.exit(),
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
surface_configured = true;
|
||||
state.resize(*physical_size);
|
||||
}
|
||||
WindowEvent::RedrawRequested => {
|
||||
// This tells winit that we want another frame after this one
|
||||
state.window().request_redraw();
|
||||
.run(move |ev, window_target| match ev {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::RedrawRequested => {
|
||||
let dt = {
|
||||
let t2 = Instant::now();
|
||||
let dt = t2 - t1;
|
||||
t1 = t2;
|
||||
dt.as_secs_f32()
|
||||
};
|
||||
cam.move_rel(100. * dt * kbd.control(&KEYS_MOVE));
|
||||
cam.rotate_rel_ypr(2. * dt * kbd.control(&KEYS_ROTATE));
|
||||
|
||||
if !surface_configured {
|
||||
return;
|
||||
}
|
||||
let size = window.inner_size();
|
||||
let size = vec2(size.width as f32, size.height as f32).normalize()
|
||||
* std::f32::consts::SQRT_2;
|
||||
let proj = make_proj_matrix(vec3(size.x, size.y, 2.), (1., 4096.));
|
||||
|
||||
state.update();
|
||||
match state.render() {
|
||||
Ok(_) => {}
|
||||
// Reconfigure the surface if it's lost or outdated
|
||||
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => {
|
||||
state.resize(state.size)
|
||||
}
|
||||
// The system is out of memory, we should probably quit
|
||||
Err(wgpu::SurfaceError::OutOfMemory) => {
|
||||
eprintln!("OutOfMemory");
|
||||
control_flow.exit();
|
||||
}
|
||||
let my_to_gl = mat4(
|
||||
vec4(0., 0., 1., 0.),
|
||||
vec4(-1., 0., 0., 0.),
|
||||
vec4(0., 1., 0., 0.),
|
||||
vec4(0., 0., 0., 1.),
|
||||
);
|
||||
let view = my_to_gl * cam.view_mtx();
|
||||
|
||||
// This happens when the a frame takes too long to present
|
||||
Err(wgpu::SurfaceError::Timeout) => {
|
||||
eprintln!("Surface timeout")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
let mut target = display.draw();
|
||||
target.clear_color(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
let mvp = proj * view;
|
||||
let params = DrawParameters {
|
||||
blend: glium::Blend {
|
||||
color: glium::BlendingFunction::Addition {
|
||||
source: glium::LinearBlendingFactor::One,
|
||||
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
||||
},
|
||||
alpha: glium::BlendingFunction::Addition {
|
||||
source: glium::LinearBlendingFactor::One,
|
||||
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
||||
},
|
||||
constant_value: (0., 0., 0., 0.),
|
||||
},
|
||||
line_width: Some(3.),
|
||||
smooth: Some(glium::Smooth::Nicest),
|
||||
..Default::default()
|
||||
};
|
||||
for mesh in &scene {
|
||||
let uniforms = uniform! {
|
||||
mvp: mvp.to_cols_array_2d(),
|
||||
color: mesh.color.to_array(),
|
||||
};
|
||||
let indices = glium::index::NoIndices(mesh.mode);
|
||||
target
|
||||
.draw(&mesh.data, &indices, &program, &uniforms, ¶ms)
|
||||
.unwrap();
|
||||
}
|
||||
target.finish().unwrap();
|
||||
}
|
||||
_ => {}
|
||||
|
||||
WindowEvent::KeyboardInput {
|
||||
device_id: _,
|
||||
event,
|
||||
is_synthetic: _,
|
||||
} => {
|
||||
kbd.set_key_state(event.physical_key, event.state);
|
||||
}
|
||||
|
||||
WindowEvent::Resized(window_size) => {
|
||||
display.resize(window_size.into());
|
||||
}
|
||||
|
||||
WindowEvent::CloseRequested => {
|
||||
window_target.exit();
|
||||
}
|
||||
|
||||
_ => (),
|
||||
},
|
||||
|
||||
Event::AboutToWait => {
|
||||
window.request_redraw();
|
||||
}
|
||||
_ => (),
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pollster::block_on(run());
|
||||
}
|
||||
|
||||
/// Make a projection matrix, assuming input coordinates are (right, up, forward).
|
||||
///
|
||||
/// `corner` is a vector that will be mapped to (x=1, y=1) after the perspective division.
|
||||
|
|
|
|||
10
src/bin/wireframe/ray.f.glsl
Normal file
10
src/bin/wireframe/ray.f.glsl
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#version 330
|
||||
|
||||
in vec3 vertex_color;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main() {
|
||||
float opacity = pow(0.5 - 0.5 * gl_FragCoord.z, 0.25);
|
||||
color = opacity * vec4(vertex_color, 1.0);
|
||||
}
|
||||
13
src/bin/wireframe/ray.v.glsl
Normal file
13
src/bin/wireframe/ray.v.glsl
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#version 330
|
||||
|
||||
uniform mat4 mvp;
|
||||
uniform vec3 color;
|
||||
|
||||
in vec3 position;
|
||||
|
||||
out vec3 vertex_color;
|
||||
|
||||
void main() {
|
||||
vertex_color = color;
|
||||
gl_Position = mvp * vec4(position, 1.0);
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
struct CameraUniform {
|
||||
mvp: mat4x4<f32>,
|
||||
}
|
||||
@group(0) @binding(0)
|
||||
var<uniform> camera: CameraUniform;
|
||||
|
||||
struct LineUniform {
|
||||
color: vec3<f32>,
|
||||
}
|
||||
var<push_constant> line: LineUniform;
|
||||
|
||||
struct VertexInput {
|
||||
@location(0) position: vec3<f32>,
|
||||
}
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) clip_position: vec4<f32>,
|
||||
@location(0) vertex_color: vec3<f32>,
|
||||
}
|
||||
|
||||
@vertex
|
||||
fn vs_main(model: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.vertex_color = line.color;
|
||||
out.clip_position = camera.mvp * vec4(model.position, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
let opacity = pow(0.5 - 0.5 * in.clip_position.z, 0.25);
|
||||
return opacity * vec4(in.vertex_color, 1.0);
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
use glam::*;
|
||||
use itertools::{chain, iproduct};
|
||||
|
||||
use refraction::ifaces::{DebugTraceable, Traceable};
|
||||
use refraction::tube::metric::Tube;
|
||||
|
|
@ -31,18 +30,6 @@ fn draw_rect(center: Vec3, u: Vec3, v: Vec3) -> Line {
|
|||
])
|
||||
}
|
||||
|
||||
fn draw_ellipse(center: Vec3, u: Vec3, v: Vec3) -> Line {
|
||||
let segments = 47;
|
||||
let step = 2. * std::f32::consts::PI / segments as f32;
|
||||
Line::Loop(
|
||||
(0..segments)
|
||||
.map(|k| k as f32 * step)
|
||||
.map(Vec2::from_angle)
|
||||
.map(|d| center + d.x * u + d.y * v)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn build() -> Vec<FancyLine> {
|
||||
let tube = Tube {
|
||||
inner_radius: 30.0,
|
||||
|
|
@ -126,18 +113,17 @@ trait Renderable {
|
|||
|
||||
impl Renderable for Tube {
|
||||
fn render(&self) -> Vec<Line> {
|
||||
let lines = 17;
|
||||
let step = 2. * std::f32::consts::PI / lines as f32;
|
||||
let r = 0.5 * (self.outer_radius + self.inner_radius);
|
||||
let w = 0.5 * (self.outer_radius - self.inner_radius);
|
||||
let l = vec3(0., self.external_halflength, 0.);
|
||||
let along = (0..lines)
|
||||
.map(|k| k as f32 * step)
|
||||
.map(Vec2::from_angle)
|
||||
.map(|d| vec3(d.x, 0., d.y))
|
||||
.map(|d| draw_rect(r * d, w * d, l));
|
||||
let caps = iproduct!([self.inner_radius, self.outer_radius], [-l, l])
|
||||
.map(|(r, l)| draw_ellipse(l, vec3(r, 0., 0.), vec3(0., 0., r)));
|
||||
chain!(along, caps).collect()
|
||||
vec![
|
||||
draw_rect(
|
||||
vec3(0., 0., 0.),
|
||||
vec3(self.outer_radius, 0., 0.),
|
||||
vec3(0., self.external_halflength, 0.),
|
||||
),
|
||||
draw_rect(
|
||||
vec3(0., 0., 0.),
|
||||
vec3(self.inner_radius, 0., 0.),
|
||||
vec3(0., self.external_halflength, 0.),
|
||||
),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user