Compare commits
2 commits
9731315e98
...
5f8b643263
Author | SHA1 | Date | |
---|---|---|---|
5f8b643263 | |||
7cf5891323 |
10 changed files with 298 additions and 0 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -2406,6 +2406,22 @@ dependencies = [
|
||||||
"utils",
|
"utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtitled15"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"nannou",
|
||||||
|
"utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtitled16"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"nannou",
|
||||||
|
"utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtitled2"
|
name = "subtitled2"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
8
crates/subtitled15/Cargo.toml
Normal file
8
crates/subtitled15/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "subtitled15"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nannou = "0.17"
|
||||||
|
utils = { path = "../utils" }
|
BIN
crates/subtitled15/shaders/frag.spv
Normal file
BIN
crates/subtitled15/shaders/frag.spv
Normal file
Binary file not shown.
13
crates/subtitled15/shaders/shader.frag
Normal file
13
crates/subtitled15/shaders/shader.frag
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// NOTE: This shader requires being manually compiled to SPIR-V in order to
|
||||||
|
// avoid having downstream users require building shaderc and compiling the
|
||||||
|
// shader themselves. If you update this shader, be sure to also re-compile it
|
||||||
|
// and update `frag.spv`. You can do so using `glslangValidator` with the
|
||||||
|
// following command: `glslangValidator -V shader.frag`
|
||||||
|
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 f_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
15
crates/subtitled15/shaders/shader.vert
Normal file
15
crates/subtitled15/shaders/shader.vert
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// NOTE: This shader requires being manually compiled to SPIR-V in order to
|
||||||
|
// avoid having downstream users require building shaderc and compiling the
|
||||||
|
// shader themselves. If you update this shader, be sure to also re-compile it
|
||||||
|
// and update `vert.spv`. You can do so using `glslangValidator` with the
|
||||||
|
// following command: `glslangValidator -V shader.vert`
|
||||||
|
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
// maybe change for this https://github.com/castor-software/rethread/blob/69a5746b02c260982a812c52da15ee364bc047e8/code/software-evolution/drift_vis/src/shaders/blur.vert
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 position;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
|
}
|
BIN
crates/subtitled15/shaders/vert.spv
Normal file
BIN
crates/subtitled15/shaders/vert.spv
Normal file
Binary file not shown.
127
crates/subtitled15/src/main.rs
Normal file
127
crates/subtitled15/src/main.rs
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
use nannou::prelude::*;
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
bind_group: wgpu::BindGroup,
|
||||||
|
render_pipeline: wgpu::RenderPipeline,
|
||||||
|
vertex_buffer1: wgpu::Buffer,
|
||||||
|
vertex_buffer2: wgpu::Buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
// The vertex type that we will use to represent a point on our triangle.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct Vertex {
|
||||||
|
position: [f32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
// The vertices that make up our triangle.
|
||||||
|
const VERTICES1: [Vertex; 3] = [
|
||||||
|
Vertex {
|
||||||
|
position: [-1.0, -1.0],
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: [1.0, 1.0],
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: [-1.0, 1.0],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const VERTICES2: [Vertex; 3] = [
|
||||||
|
Vertex {
|
||||||
|
position: [1.0, -1.0],
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: [1.0, 1.0],
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: [-1.0, -1.0],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
nannou::app(model).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn model(app: &App) -> Model {
|
||||||
|
let w_id = app.new_window().size(512, 512).view(view).build().unwrap();
|
||||||
|
|
||||||
|
// The gpu device associated with the window's swapchain
|
||||||
|
let window = app.window(w_id).unwrap();
|
||||||
|
let device = window.swap_chain_device();
|
||||||
|
let format = Frame::TEXTURE_FORMAT;
|
||||||
|
let sample_count = window.msaa_samples();
|
||||||
|
|
||||||
|
// Load shader modules.
|
||||||
|
let vs_mod = wgpu::shader_from_spirv_bytes(device, include_bytes!("../shaders/vert.spv"));
|
||||||
|
let fs_mod = wgpu::shader_from_spirv_bytes(device, include_bytes!("../shaders/frag.spv"));
|
||||||
|
|
||||||
|
// Create the vertex buffer.
|
||||||
|
let usage = wgpu::BufferUsage::VERTEX;
|
||||||
|
let vertices_bytes = vertices_as_bytes(&VERTICES1[..]);
|
||||||
|
let vertex_buffer1 = device.create_buffer_init(&BufferInitDescriptor {
|
||||||
|
label: None,
|
||||||
|
contents: vertices_bytes,
|
||||||
|
usage,
|
||||||
|
});
|
||||||
|
let vertices_bytes = vertices_as_bytes(&VERTICES2[..]);
|
||||||
|
let vertex_buffer2 = device.create_buffer_init(&BufferInitDescriptor {
|
||||||
|
label: None,
|
||||||
|
contents: vertices_bytes,
|
||||||
|
usage,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the render pipeline.
|
||||||
|
let bind_group_layout = wgpu::BindGroupLayoutBuilder::new().build(device);
|
||||||
|
let bind_group = wgpu::BindGroupBuilder::new().build(device, &bind_group_layout);
|
||||||
|
let pipeline_layout = wgpu::create_pipeline_layout(device, None, &[&bind_group_layout], &[]);
|
||||||
|
let render_pipeline = wgpu::RenderPipelineBuilder::from_layout(&pipeline_layout, &vs_mod)
|
||||||
|
.fragment_shader(&fs_mod)
|
||||||
|
.color_format(format)
|
||||||
|
.add_vertex_buffer::<Vertex>(&wgpu::vertex_attr_array![0 => Float32x2])
|
||||||
|
.sample_count(sample_count)
|
||||||
|
.build(device);
|
||||||
|
|
||||||
|
Model {
|
||||||
|
bind_group,
|
||||||
|
vertex_buffer1,
|
||||||
|
vertex_buffer2,
|
||||||
|
render_pipeline,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the state of your `Model` into the given `Frame` here.
|
||||||
|
fn view(_app: &App, model: &Model, frame: Frame) {
|
||||||
|
// Using this we will encode commands that will be submitted to the GPU.
|
||||||
|
let mut encoder = frame.command_encoder();
|
||||||
|
|
||||||
|
// The render pass can be thought of a single large command consisting of sub commands. Here we
|
||||||
|
// begin a render pass that outputs to the frame's texture. Then we add sub-commands for
|
||||||
|
// setting the bind group, render pipeline, vertex buffers and then finally drawing.
|
||||||
|
let mut render_pass = wgpu::RenderPassBuilder::new()
|
||||||
|
.color_attachment(frame.texture_view(), |color| color)
|
||||||
|
.begin(&mut encoder);
|
||||||
|
render_pass.set_bind_group(0, &model.bind_group, &[]);
|
||||||
|
render_pass.set_pipeline(&model.render_pipeline);
|
||||||
|
render_pass.set_vertex_buffer(0, model.vertex_buffer1.slice(..));
|
||||||
|
|
||||||
|
// We want to draw the whole range of vertices, and we're only drawing one instance of them.
|
||||||
|
let vertex_range = 0..VERTICES1.len() as u32;
|
||||||
|
let instance_range = 0..1;
|
||||||
|
render_pass.draw(vertex_range, instance_range);
|
||||||
|
|
||||||
|
render_pass.set_bind_group(0, &model.bind_group, &[]);
|
||||||
|
render_pass.set_pipeline(&model.render_pipeline);
|
||||||
|
render_pass.set_vertex_buffer(0, model.vertex_buffer2.slice(..));
|
||||||
|
|
||||||
|
// We want to draw the whole range of vertices, and we're only drawing one instance of them.
|
||||||
|
let vertex_range = 0..VERTICES2.len() as u32;
|
||||||
|
let instance_range = 0..1;
|
||||||
|
render_pass.draw(vertex_range, instance_range);
|
||||||
|
|
||||||
|
// Now we're done! The commands we added will be submitted after `view` completes.
|
||||||
|
}
|
||||||
|
|
||||||
|
// See the `nannou::wgpu::bytes` documentation for why this is necessary.
|
||||||
|
fn vertices_as_bytes(data: &[Vertex]) -> &[u8] {
|
||||||
|
unsafe { wgpu::bytes::from_slice(data) }
|
||||||
|
}
|
8
crates/subtitled16/Cargo.toml
Normal file
8
crates/subtitled16/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "subtitled16"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nannou = "0.17"
|
||||||
|
utils = { path = "../utils" }
|
108
crates/subtitled16/src/main.rs
Normal file
108
crates/subtitled16/src/main.rs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use nannou::prelude::*;
|
||||||
|
|
||||||
|
const R: f32 = 2.0;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
nannou::app(model).update(update).simple_window(view).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Point {
|
||||||
|
pos: IVec2,
|
||||||
|
color: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Point {
|
||||||
|
fn new(pos: IVec2, color: f32) -> Self {
|
||||||
|
Self { pos, color }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn neighbors(point: IVec2) -> Vec<IVec2> {
|
||||||
|
let mut cube = vec![];
|
||||||
|
let p = [-1, 0, 1];
|
||||||
|
for &x in &p {
|
||||||
|
for &y in &p {
|
||||||
|
if (x, y) != (0, 0) {
|
||||||
|
cube.push(ivec2(x, y) + point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cube
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
points: Vec<Point>,
|
||||||
|
visits: Vec<Point>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn model(_app: &App) -> Model {
|
||||||
|
Model {
|
||||||
|
visits: vec![Point::new(IVec2::ZERO, random_range(0.0, 360.0))],
|
||||||
|
points: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||||
|
for _ in 0..20 {
|
||||||
|
run(app, model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn run(app: &App, model: &mut Model) {
|
||||||
|
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||||
|
|
||||||
|
// take a random out of the visits list
|
||||||
|
let point = model.visits.remove(random_range(0, model.visits.len()));
|
||||||
|
// visit it and all it's neighbors
|
||||||
|
let neighbors = neighbors(point.pos)
|
||||||
|
.into_iter()
|
||||||
|
.filter(|p| {
|
||||||
|
model.visits.iter().find(|point| point.pos == *p).is_none()
|
||||||
|
&& model.points.iter().find(|point| point.pos == *p).is_none()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
for n in neighbors {
|
||||||
|
model
|
||||||
|
.visits
|
||||||
|
// NOTE: this is where the randomization of the color happens
|
||||||
|
.push(Point::new(n, point.color + random_range(-10.0, 10.0)))
|
||||||
|
}
|
||||||
|
// move it to visited points
|
||||||
|
model.points.push(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(app: &App, model: &Model, frame: Frame) {
|
||||||
|
let _t = frame.nth() as f32 / 60.0;
|
||||||
|
|
||||||
|
let draw = app.draw();
|
||||||
|
draw.background().color(SNOW);
|
||||||
|
|
||||||
|
for walker in &model.visits {
|
||||||
|
let h = walker.color / 360.0;
|
||||||
|
draw.ellipse()
|
||||||
|
.xy(walker.pos.as_f32() * R * 2.0)
|
||||||
|
.radius(R)
|
||||||
|
.color(hsl(h.fract(), 0.5, 0.7));
|
||||||
|
}
|
||||||
|
for walker in &model.points {
|
||||||
|
let h = walker.color / 360.0;
|
||||||
|
let p = walker.pos.as_f32() * R;
|
||||||
|
draw.quad()
|
||||||
|
.points(
|
||||||
|
p + R * vec2(1., 1.),
|
||||||
|
p + R * vec2(1., -1.),
|
||||||
|
p + R * vec2(-1., -1.),
|
||||||
|
p + R * vec2(-1., 1.),
|
||||||
|
)
|
||||||
|
.xy(p)
|
||||||
|
.color(hsl(h.fract(), 0.5, 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
// cause otherwise it goes too fast when recording and it can't save the frames in time lmao
|
||||||
|
std::thread::sleep(Duration::from_millis(5));
|
||||||
|
|
||||||
|
draw.to_frame(app, &frame).unwrap();
|
||||||
|
utils::record::record(app, &frame);
|
||||||
|
}
|
|
@ -46,3 +46,6 @@ impl Tup2Extension for (f32, f32) {
|
||||||
pub fn vec2_range(min: f32, max: f32) -> Vec2 {
|
pub fn vec2_range(min: f32, max: f32) -> Vec2 {
|
||||||
vec2(random_range(min, max), random_range(min, max))
|
vec2(random_range(min, max), random_range(min, max))
|
||||||
}
|
}
|
||||||
|
pub fn ivec2_range(min: i32, max: i32) -> IVec2 {
|
||||||
|
ivec2(random_range(min, max), random_range(min, max))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue