Compare commits
4 Commits
dbdcdde80d
...
c1b505356c
| Author | SHA1 | Date | |
|---|---|---|---|
| c1b505356c | |||
| 30f02e4ff2 | |||
| f00f5f2f77 | |||
| 03e91fac28 |
|
|
@ -10,6 +10,7 @@ use winit::{
|
||||||
|
|
||||||
mod camera;
|
mod camera;
|
||||||
mod lines;
|
mod lines;
|
||||||
|
mod meshes;
|
||||||
mod scene;
|
mod scene;
|
||||||
mod viewport;
|
mod viewport;
|
||||||
|
|
||||||
|
|
@ -18,11 +19,17 @@ mod viewport;
|
||||||
// * Y: left
|
// * Y: left
|
||||||
// * Z: up
|
// * Z: up
|
||||||
|
|
||||||
fn prepare_scene(device: &wgpu::Device) -> Vec<lines::Line> {
|
fn prepare_scene(device: &wgpu::Device) -> (Vec<meshes::Mesh>, Vec<lines::Line>) {
|
||||||
scene::build()
|
let (meshes, lines) = scene::build();
|
||||||
|
let meshes = meshes
|
||||||
|
.into_iter()
|
||||||
|
.map(|mesh| meshes::Mesh::new_list(device, meshes::Attrs { color: mesh.color }, mesh.tris))
|
||||||
|
.collect();
|
||||||
|
let lines = lines
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|line| lines::Line::new_strip(device, lines::Attrs { color: line.color }, line.pts))
|
.map(|line| lines::Line::new_strip(device, lines::Attrs { color: line.color }, line.pts))
|
||||||
.collect()
|
.collect();
|
||||||
|
(meshes, lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any())]
|
#[cfg(any())]
|
||||||
|
|
@ -160,8 +167,10 @@ struct State<'a> {
|
||||||
cam_loc: camctl::CameraLocation,
|
cam_loc: camctl::CameraLocation,
|
||||||
cam_obj: camera::Camera,
|
cam_obj: camera::Camera,
|
||||||
line_rend: lines::LineRenderer,
|
line_rend: lines::LineRenderer,
|
||||||
|
mesh_rend: meshes::Renderer,
|
||||||
|
|
||||||
scene: Vec<lines::Line>,
|
lines: Vec<lines::Line>,
|
||||||
|
meshes: Vec<meshes::Mesh>,
|
||||||
|
|
||||||
window: &'a Window,
|
window: &'a Window,
|
||||||
}
|
}
|
||||||
|
|
@ -206,17 +215,43 @@ impl<'a> State<'a> {
|
||||||
let cam_loc = camctl::CameraLocation::new();
|
let cam_loc = camctl::CameraLocation::new();
|
||||||
let t1 = Instant::now();
|
let t1 = Instant::now();
|
||||||
|
|
||||||
let depth = None;
|
|
||||||
let msaa = wgpu::MultisampleState {
|
|
||||||
count: viewport.sample_count(),
|
|
||||||
mask: !0,
|
|
||||||
alpha_to_coverage_enabled: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let cam_obj = camera::Camera::new(&device);
|
let cam_obj = camera::Camera::new(&device);
|
||||||
let line_rend = lines::LineRenderer::new(&device, cam_obj.bind_group_layout(), viewport.format(), depth, msaa);
|
let line_rend = lines::LineRenderer::new(
|
||||||
|
&device,
|
||||||
|
cam_obj.bind_group_layout(),
|
||||||
|
viewport.format(),
|
||||||
|
Some(wgpu::DepthStencilState {
|
||||||
|
format: wgpu::TextureFormat::Depth24Plus,
|
||||||
|
depth_write_enabled: false,
|
||||||
|
depth_compare: wgpu::CompareFunction::LessEqual,
|
||||||
|
stencil: wgpu::StencilState::default(),
|
||||||
|
bias: wgpu::DepthBiasState::default(),
|
||||||
|
}),
|
||||||
|
wgpu::MultisampleState {
|
||||||
|
count: viewport.sample_count(),
|
||||||
|
mask: !0,
|
||||||
|
alpha_to_coverage_enabled: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let mesh_rend = meshes::Renderer::new(
|
||||||
|
&device,
|
||||||
|
cam_obj.bind_group_layout(),
|
||||||
|
viewport.format(),
|
||||||
|
Some(wgpu::DepthStencilState {
|
||||||
|
format: wgpu::TextureFormat::Depth24Plus,
|
||||||
|
depth_write_enabled: true,
|
||||||
|
depth_compare: wgpu::CompareFunction::LessEqual,
|
||||||
|
stencil: wgpu::StencilState::default(),
|
||||||
|
bias: wgpu::DepthBiasState::default(),
|
||||||
|
}),
|
||||||
|
wgpu::MultisampleState {
|
||||||
|
count: viewport.sample_count(),
|
||||||
|
mask: !0,
|
||||||
|
alpha_to_coverage_enabled: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let scene = prepare_scene(&device);
|
let (meshes, lines) = prepare_scene(&device);
|
||||||
|
|
||||||
let fps = fps::Counter::new();
|
let fps = fps::Counter::new();
|
||||||
|
|
||||||
|
|
@ -225,12 +260,14 @@ impl<'a> State<'a> {
|
||||||
queue,
|
queue,
|
||||||
viewport,
|
viewport,
|
||||||
line_rend,
|
line_rend,
|
||||||
|
mesh_rend,
|
||||||
kbd,
|
kbd,
|
||||||
fps,
|
fps,
|
||||||
cam_loc,
|
cam_loc,
|
||||||
cam_obj,
|
cam_obj,
|
||||||
t1,
|
t1,
|
||||||
scene,
|
lines,
|
||||||
|
meshes,
|
||||||
window,
|
window,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -266,8 +303,10 @@ impl<'a> State<'a> {
|
||||||
.set_title(&format!("Space Refraction ({:.1} FPS)", self.fps.get()));
|
.set_title(&format!("Space Refraction ({:.1} FPS)", self.fps.get()));
|
||||||
self.viewport
|
self.viewport
|
||||||
.render_single_pass(&self.device, &self.queue, |mut render_pass| {
|
.render_single_pass(&self.device, &self.queue, |mut render_pass| {
|
||||||
|
self.mesh_rend
|
||||||
|
.render(&mut render_pass, self.cam_obj.bind_group(), self.meshes.iter());
|
||||||
self.line_rend
|
self.line_rend
|
||||||
.render(&mut render_pass, self.cam_obj.bind_group(), self.scene.iter());
|
.render(&mut render_pass, self.cam_obj.bind_group(), self.lines.iter());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
63
src/bin/wireframe/mesh.wgsl
Normal file
63
src/bin/wireframe/mesh.wgsl
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
struct CameraUniform {
|
||||||
|
mvp: mat4x4<f32>,
|
||||||
|
scale: vec2<f32>,
|
||||||
|
}
|
||||||
|
@group(0) @binding(0)
|
||||||
|
var<uniform> camera: CameraUniform;
|
||||||
|
|
||||||
|
struct MeshUniform {
|
||||||
|
color: vec4<f32>,
|
||||||
|
}
|
||||||
|
var<push_constant> mesh: MeshUniform;
|
||||||
|
|
||||||
|
struct VertexInput {
|
||||||
|
@location(0) position: vec3<f32>,
|
||||||
|
@location(1) normal: vec3<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VertexOutput {
|
||||||
|
@builtin(position) clip_position: vec4<f32>,
|
||||||
|
@location(0) vertex_color: vec4<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FragmentOutput {
|
||||||
|
@location(0) color: vec4<f32>,
|
||||||
|
@builtin(sample_mask) mask: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash(key : u32) -> u32 {
|
||||||
|
var v = key;
|
||||||
|
v *= 0xb384af1bu;
|
||||||
|
v ^= v >> 15u;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vs_main(ver: VertexInput) -> VertexOutput {
|
||||||
|
var out: VertexOutput;
|
||||||
|
var light = dot(ver.normal, normalize(vec3(1., 1., 1.)));
|
||||||
|
light = .7 + .3 * light;
|
||||||
|
out.vertex_color = vec4(light * mesh.color.xyz, mesh.color.w);
|
||||||
|
out.clip_position = camera.mvp * vec4(ver.position, 1.);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn fs_main(in: VertexOutput) -> FragmentOutput {
|
||||||
|
var out: FragmentOutput;
|
||||||
|
out.color = vec4(in.vertex_color.xyz, 1.);
|
||||||
|
var x = bitcast<u32>(in.clip_position.x);
|
||||||
|
var y = bitcast<u32>(in.clip_position.y);
|
||||||
|
var z = bitcast<u32>(in.clip_position.z);
|
||||||
|
var alpha = in.vertex_color.w;
|
||||||
|
var seed = hash(hash(hash(x) ^ y) ^ z);
|
||||||
|
var mask = 0u;
|
||||||
|
for (var sample = 0u; sample < 8u; sample++) {
|
||||||
|
var threshold = f32(hash(seed ^ sample)) / 0x1p32;
|
||||||
|
if (alpha > threshold) {
|
||||||
|
mask |= 1u << sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.mask = mask;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
168
src/bin/wireframe/meshes.rs
Normal file
168
src/bin/wireframe/meshes.rs
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
use bytemuck::{bytes_of, cast_slice, Pod, Zeroable};
|
||||||
|
use glam::{Vec3, Vec4};
|
||||||
|
use wgpu::util::DeviceExt as _;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
|
||||||
|
struct Vertex {
|
||||||
|
pub position: [f32; 3],
|
||||||
|
pub normal: [f32; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||||
|
struct PushConsts {
|
||||||
|
pub color: [f32; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Attrs {
|
||||||
|
pub color: Vec4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Attrs {
|
||||||
|
fn consts(&self) -> PushConsts {
|
||||||
|
PushConsts {
|
||||||
|
color: self.color.to_array(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Mesh {
|
||||||
|
consts: PushConsts,
|
||||||
|
npoints: u32,
|
||||||
|
buf: wgpu::Buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mesh {
|
||||||
|
pub fn new_list(device: &wgpu::Device, attrs: Attrs, tris: Vec<(Vec3, Vec3, Vec3)>) -> Self {
|
||||||
|
let data: Vec<Vertex> = tris
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|(a, b, c)| {
|
||||||
|
let n = (b - a).cross(c - a).normalize();
|
||||||
|
[
|
||||||
|
Vertex {
|
||||||
|
position: a.into(),
|
||||||
|
normal: n.into(),
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: b.into(),
|
||||||
|
normal: n.into(),
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: c.into(),
|
||||||
|
normal: n.into(),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Mesh Vertex Buffer"),
|
||||||
|
contents: cast_slice(&data),
|
||||||
|
usage: wgpu::BufferUsages::VERTEX,
|
||||||
|
});
|
||||||
|
Mesh {
|
||||||
|
consts: attrs.consts(),
|
||||||
|
npoints: data.len() as u32,
|
||||||
|
buf,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Renderer {
|
||||||
|
pipeline: wgpu::RenderPipeline,
|
||||||
|
}
|
||||||
|
|
||||||
|
static SHADER: &'static str = include_str!("mesh.wgsl");
|
||||||
|
|
||||||
|
impl Renderer {
|
||||||
|
pub fn new(
|
||||||
|
device: &wgpu::Device,
|
||||||
|
cam_layout: &wgpu::BindGroupLayout,
|
||||||
|
target_format: wgpu::TextureFormat,
|
||||||
|
depth_stencil: Option<wgpu::DepthStencilState>,
|
||||||
|
multisample: wgpu::MultisampleState,
|
||||||
|
) -> Renderer {
|
||||||
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
|
label: Some("Mesh Shader"),
|
||||||
|
source: wgpu::ShaderSource::Wgsl(SHADER.into()),
|
||||||
|
});
|
||||||
|
|
||||||
|
let consts_range = wgpu::PushConstantRange {
|
||||||
|
stages: wgpu::ShaderStages::VERTEX,
|
||||||
|
range: 0..mem::size_of::<PushConsts>() as u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
label: Some("Mesh RenderPipelineLayout"),
|
||||||
|
bind_group_layouts: &[cam_layout],
|
||||||
|
push_constant_ranges: &[consts_range],
|
||||||
|
});
|
||||||
|
|
||||||
|
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
|
label: Some("Mesh RenderPipeline"),
|
||||||
|
layout: Some(&layout),
|
||||||
|
vertex: wgpu::VertexState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: "vs_main",
|
||||||
|
buffers: &[wgpu::VertexBufferLayout {
|
||||||
|
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
|
||||||
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
|
attributes: &[
|
||||||
|
wgpu::VertexAttribute {
|
||||||
|
offset: mem::offset_of!(Vertex, position) as u64,
|
||||||
|
shader_location: 0,
|
||||||
|
format: wgpu::VertexFormat::Float32x3,
|
||||||
|
},
|
||||||
|
wgpu::VertexAttribute {
|
||||||
|
offset: mem::offset_of!(Vertex, normal) as u64,
|
||||||
|
shader_location: 1,
|
||||||
|
format: wgpu::VertexFormat::Float32x3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
compilation_options: Default::default(),
|
||||||
|
},
|
||||||
|
fragment: Some(wgpu::FragmentState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: "fs_main",
|
||||||
|
targets: &[Some(wgpu::ColorTargetState {
|
||||||
|
format: target_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::TriangleList,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
depth_stencil,
|
||||||
|
multisample,
|
||||||
|
multiview: None,
|
||||||
|
cache: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
Renderer { pipeline }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render<'a>(
|
||||||
|
&self,
|
||||||
|
pass: &mut wgpu::RenderPass,
|
||||||
|
cam_bind: &wgpu::BindGroup,
|
||||||
|
meshes: impl Iterator<Item = &'a Mesh>,
|
||||||
|
) {
|
||||||
|
pass.set_pipeline(&self.pipeline);
|
||||||
|
pass.set_bind_group(0, cam_bind, &[]);
|
||||||
|
for mesh in meshes {
|
||||||
|
pass.set_push_constants(wgpu::ShaderStages::VERTEX, 0, bytes_of(&mesh.consts));
|
||||||
|
pass.set_vertex_buffer(0, mesh.buf.slice(..));
|
||||||
|
pass.draw(0..mesh.npoints, 0..1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use glam::*;
|
use glam::*;
|
||||||
use itertools::{chain, iproduct};
|
use itertools::chain;
|
||||||
|
|
||||||
use refraction::ifaces::{DebugTraceable, Traceable};
|
use refraction::ifaces::{DebugTraceable, Traceable};
|
||||||
use refraction::tube::metric::Tube;
|
use refraction::tube::metric::Tube;
|
||||||
|
|
@ -17,6 +17,17 @@ pub struct FancyLine {
|
||||||
pub pts: Vec<Ray>,
|
pub pts: Vec<Ray>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type Face = (Vec3, Vec3, Vec3);
|
||||||
|
|
||||||
|
pub enum Mesh {
|
||||||
|
List(Vec<Face>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FancyMesh {
|
||||||
|
pub color: Vec4,
|
||||||
|
pub tris: Vec<Face>,
|
||||||
|
}
|
||||||
|
|
||||||
fn paint(onto: &mut Vec<FancyLine>, color: Vec3, lines: Vec<Line>) {
|
fn paint(onto: &mut Vec<FancyLine>, color: Vec3, lines: Vec<Line>) {
|
||||||
onto.extend(lines.into_iter().map(move |line| FancyLine {
|
onto.extend(lines.into_iter().map(move |line| FancyLine {
|
||||||
color,
|
color,
|
||||||
|
|
@ -35,29 +46,6 @@ fn draw_line(a: Vec3, b: Vec3) -> Line {
|
||||||
Line::Strip(vec![Ray { pos: a, dir }, Ray { pos: b, dir }])
|
Line::Strip(vec![Ray { pos: a, dir }, Ray { pos: b, dir }])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_rect(center: Vec3, u: Vec3, v: Vec3) -> Vec<Line> {
|
|
||||||
let a = center - u - v;
|
|
||||||
let b = center + u - v;
|
|
||||||
let c = center + u + v;
|
|
||||||
let d = center - u + v;
|
|
||||||
vec![draw_line(a, b), draw_line(b, c), draw_line(c, d), draw_line(d, a)]
|
|
||||||
}
|
|
||||||
|
|
||||||
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| Ray {
|
|
||||||
pos: center + d.x * u + d.y * v,
|
|
||||||
dir: -d.y * u + d.x * v,
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_mark(pos: Vec3) -> Vec<Line> {
|
fn draw_mark(pos: Vec3) -> Vec<Line> {
|
||||||
[
|
[
|
||||||
vec3(1., 1., 1.),
|
vec3(1., 1., 1.),
|
||||||
|
|
@ -70,7 +58,7 @@ fn draw_mark(pos: Vec3) -> Vec<Line> {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build() -> Vec<FancyLine> {
|
pub fn build() -> (Vec<FancyMesh>, Vec<FancyLine>) {
|
||||||
let tube = Tube {
|
let tube = Tube {
|
||||||
inner_radius: 30.0,
|
inner_radius: 30.0,
|
||||||
outer_radius: 50.0,
|
outer_radius: 50.0,
|
||||||
|
|
@ -110,7 +98,13 @@ pub fn build() -> Vec<FancyLine> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut gc = vec![];
|
let mut gc = vec![];
|
||||||
paint(&mut gc, vec3(0.6, 0.6, 0.6), tube.render());
|
gc.push(FancyMesh {
|
||||||
|
color: vec4(0.10, 0.12, 0.15, 0.8),
|
||||||
|
tris: tube.render(),
|
||||||
|
});
|
||||||
|
let meshes = gc;
|
||||||
|
|
||||||
|
let mut gc = vec![];
|
||||||
paint(&mut gc, vec3(0.0, 0.6, 1.0), draw_fan_2(&space, cam3, vec3(0., 1., 0.)));
|
paint(&mut gc, vec3(0.0, 0.6, 1.0), draw_fan_2(&space, cam3, vec3(0., 1., 0.)));
|
||||||
paint(&mut gc, vec3(0.2, 1.0, 0.0), draw_fan_2(&space, cam2, vec3(0., 1., 0.)));
|
paint(&mut gc, vec3(0.2, 1.0, 0.0), draw_fan_2(&space, cam2, vec3(0., 1., 0.)));
|
||||||
paint(
|
paint(
|
||||||
|
|
@ -119,7 +113,9 @@ pub fn build() -> Vec<FancyLine> {
|
||||||
draw_fan_2(&space, cam2l, vec3(0., 0., 1.)),
|
draw_fan_2(&space, cam2l, vec3(0., 0., 1.)),
|
||||||
);
|
);
|
||||||
paint(&mut gc, vec3(1.0, 0.2, 0.0), draw_fan_2(&space, cam1, vec3(0., 1., 0.)));
|
paint(&mut gc, vec3(1.0, 0.2, 0.0), draw_fan_2(&space, cam1, vec3(0., 1., 0.)));
|
||||||
gc
|
let lines = gc;
|
||||||
|
|
||||||
|
(meshes, lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_ray_2(gc: &mut Vec<Line>, space: &Space, camera: Location, dir: Vec3) {
|
fn draw_ray_2(gc: &mut Vec<Line>, space: &Space, camera: Location, dir: Vec3) {
|
||||||
|
|
@ -153,23 +149,42 @@ fn draw_fan_2(space: &Space, camera: Location, spread: Vec3) -> Vec<Line> {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Renderable {
|
trait Renderable {
|
||||||
fn render(&self) -> Vec<Line>;
|
fn render(&self) -> Vec<Face>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderable for Tube {
|
impl Renderable for Tube {
|
||||||
fn render(&self) -> Vec<Line> {
|
fn render(&self) -> Vec<Face> {
|
||||||
let lines = 4;
|
let sides = 42;
|
||||||
let step = 2. * std::f32::consts::PI / lines as f32;
|
let step = 2. * std::f32::consts::PI / sides as f32;
|
||||||
let r = 0.5 * (self.outer_radius + self.inner_radius);
|
let dir = |k| {
|
||||||
let w = 0.5 * (self.outer_radius - self.inner_radius);
|
let d = Vec2::from_angle(k as f32 * step);
|
||||||
let l = vec3(0., self.external_halflength, 0.);
|
vec3(d.x, 0., d.y)
|
||||||
let along = (0..lines)
|
};
|
||||||
.map(|k| k as f32 * step)
|
let side = vec3(0., self.external_halflength, 0.);
|
||||||
.map(Vec2::from_angle)
|
let r1 = self.inner_radius;
|
||||||
.map(|d| vec3(d.x, 0., d.y))
|
let r2 = self.outer_radius;
|
||||||
.flat_map(|d| draw_rect(r * d, w * d, l));
|
let inner = (0..sides).flat_map(|k| {
|
||||||
let caps = iproduct!([self.inner_radius, self.outer_radius], [-l, l])
|
let a = r1 * dir(k);
|
||||||
.map(|(r, l)| draw_ellipse(l, vec3(r, 0., 0.), vec3(0., 0., r)));
|
let b = r1 * dir(k + 1);
|
||||||
chain!(along, caps).collect()
|
[(a - side, b - side, a + side), (b - side, b + side, a + side)]
|
||||||
|
});
|
||||||
|
let outer = (0..sides).flat_map(|k| {
|
||||||
|
let a = r2 * dir(k);
|
||||||
|
let b = r2 * dir(k + 1);
|
||||||
|
[(a - side, b - side, a + side), (b - side, b + side, a + side)]
|
||||||
|
});
|
||||||
|
let cap = (0..sides).flat_map(|k| {
|
||||||
|
let a = r1 * dir(k);
|
||||||
|
let b = r1 * dir(k + 1);
|
||||||
|
let c = r2 * dir(k + 1);
|
||||||
|
let d = r2 * dir(k);
|
||||||
|
[
|
||||||
|
(a - side, b - side, c - side),
|
||||||
|
(a - side, c - side, d - side),
|
||||||
|
(a + side, b + side, c + side),
|
||||||
|
(a + side, c + side, d + side),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
chain!(inner, outer, cap).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ impl<'a> Viewport<'a> {
|
||||||
let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
label: Some("RenderPass"),
|
label: Some("RenderPass"),
|
||||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
view: &self.multisample.view,
|
view: &self.multisample.color,
|
||||||
resolve_target: Some(&view),
|
resolve_target: Some(&view),
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
load: wgpu::LoadOp::Clear(wgpu::Color {
|
||||||
|
|
@ -87,7 +87,14 @@ impl<'a> Viewport<'a> {
|
||||||
store: wgpu::StoreOp::Store,
|
store: wgpu::StoreOp::Store,
|
||||||
},
|
},
|
||||||
})],
|
})],
|
||||||
depth_stencil_attachment: None,
|
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
|
||||||
|
view: &self.multisample.depth,
|
||||||
|
depth_ops: Some(wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Clear(1.),
|
||||||
|
store: wgpu::StoreOp::Discard,
|
||||||
|
}),
|
||||||
|
stencil_ops: None,
|
||||||
|
}),
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
});
|
});
|
||||||
|
|
@ -99,13 +106,14 @@ impl<'a> Viewport<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Multisample {
|
struct Multisample {
|
||||||
view: wgpu::TextureView,
|
color: wgpu::TextureView,
|
||||||
|
depth: wgpu::TextureView,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Multisample {
|
impl Multisample {
|
||||||
fn new(device: &wgpu::Device, format: wgpu::TextureFormat, size: UVec2, sample_count: u32) -> Multisample {
|
fn new(device: &wgpu::Device, format: wgpu::TextureFormat, size: UVec2, sample_count: u32) -> Multisample {
|
||||||
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
let color = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
label: Some("Multisample texture"),
|
label: Some("Multisample color texture"),
|
||||||
size: wgpu::Extent3d {
|
size: wgpu::Extent3d {
|
||||||
width: size.x,
|
width: size.x,
|
||||||
height: size.y,
|
height: size.y,
|
||||||
|
|
@ -118,7 +126,22 @@ impl Multisample {
|
||||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||||
view_formats: &[],
|
view_formats: &[],
|
||||||
});
|
});
|
||||||
let view = tex.create_view(&wgpu::TextureViewDescriptor::default());
|
let color = color.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
Multisample { view }
|
let depth = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: Some("Multisample depth texture"),
|
||||||
|
size: wgpu::Extent3d {
|
||||||
|
width: size.x,
|
||||||
|
height: size.y,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: wgpu::TextureFormat::Depth24Plus,
|
||||||
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||||
|
view_formats: &[],
|
||||||
|
});
|
||||||
|
let depth = depth.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
Multisample { color, depth }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user