Merge branch 'glare1' into daylight
This commit is contained in:
commit
3e4de46b50
|
|
@ -1,6 +1,7 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use glam::uvec2;
|
use glam::{uvec2, vec2};
|
||||||
|
use raytracing3::glare::Glarer;
|
||||||
use raytracing3::present::{self, Presenter};
|
use raytracing3::present::{self, Presenter};
|
||||||
use raytracing3::scene::{Renderer, SceneParams};
|
use raytracing3::scene::{Renderer, SceneParams};
|
||||||
use winit::{
|
use winit::{
|
||||||
|
|
@ -27,6 +28,7 @@ fn main() {
|
||||||
let hdr_format = wgpu::TextureFormat::Rgba16Float;
|
let hdr_format = wgpu::TextureFormat::Rgba16Float;
|
||||||
let scene = SceneParams::new(N_SPHERES);
|
let scene = SceneParams::new(N_SPHERES);
|
||||||
let renderer = Renderer::new(&device);
|
let renderer = Renderer::new(&device);
|
||||||
|
let glarer = Glarer::new(&device, hdr_format);
|
||||||
let presenter = Presenter::new(&device, output_format);
|
let presenter = Presenter::new(&device, output_format);
|
||||||
|
|
||||||
let mut frame = 0;
|
let mut frame = 0;
|
||||||
|
|
@ -72,13 +74,13 @@ fn main() {
|
||||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
|
||||||
view_formats: &[],
|
view_formats: &[],
|
||||||
});
|
});
|
||||||
let hdr = hdr.create_view(&wgpu::TextureViewDescriptor::default());
|
let hdr1v = hdr.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||||
{
|
{
|
||||||
let mut render_pass = renderer.prepare(&mut encoder, &hdr);
|
let mut render_pass = renderer.prepare(&mut encoder, &hdr1v);
|
||||||
|
let time = frame as f32 / (60. * RAYS_PER_PIXEL as f32);
|
||||||
for _ in 0..RAYS_PER_PIXEL {
|
for _ in 0..RAYS_PER_PIXEL {
|
||||||
frame += 1;
|
frame += 1;
|
||||||
let time = frame as f32 / (60. * RAYS_PER_PIXEL as f32);
|
|
||||||
renderer.render_frame(
|
renderer.render_frame(
|
||||||
&device,
|
&device,
|
||||||
&mut render_pass,
|
&mut render_pass,
|
||||||
|
|
@ -89,10 +91,12 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let sigma = vec2(size.width as f32, size.height as f32).length();
|
||||||
|
glarer.render(&device, &mut encoder, &hdr, raytracing3::glare::Params { sigma });
|
||||||
presenter.render(
|
presenter.render(
|
||||||
&device,
|
&device,
|
||||||
&mut encoder,
|
&mut encoder,
|
||||||
&hdr,
|
&hdr1v,
|
||||||
&view,
|
&view,
|
||||||
present::Params {
|
present::Params {
|
||||||
divisor: RAYS_PER_PIXEL as f32,
|
divisor: RAYS_PER_PIXEL as f32,
|
||||||
|
|
|
||||||
222
src/glare.rs
Normal file
222
src/glare.rs
Normal file
|
|
@ -0,0 +1,222 @@
|
||||||
|
use std::mem::offset_of;
|
||||||
|
|
||||||
|
use bytemuck::{bytes_of, Pod, Zeroable};
|
||||||
|
use glam::{vec2, UVec2, Vec2};
|
||||||
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct Vertex {
|
||||||
|
pub screen: Vec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Params {
|
||||||
|
pub sigma: f32, // in pixels
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Glarer {
|
||||||
|
view_buf: wgpu::Buffer,
|
||||||
|
format: wgpu::TextureFormat,
|
||||||
|
pipeline_h: wgpu::RenderPipeline,
|
||||||
|
pipeline_v: wgpu::RenderPipeline,
|
||||||
|
}
|
||||||
|
|
||||||
|
static SHADER: &str = include_str!("glare.wgsl");
|
||||||
|
|
||||||
|
impl Glarer {
|
||||||
|
pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self {
|
||||||
|
let view_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: None,
|
||||||
|
contents: bytes_of(&[(0., 0.), (1., 0.), (0., 1.), (1., 1.)].map(|(x, y)| Vertex { screen: vec2(x, y) })),
|
||||||
|
usage: wgpu::BufferUsages::VERTEX,
|
||||||
|
});
|
||||||
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
|
label: None,
|
||||||
|
source: wgpu::ShaderSource::Wgsl(SHADER.into()),
|
||||||
|
});
|
||||||
|
let vertex_state = wgpu::VertexState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: None,
|
||||||
|
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
|
buffers: &[wgpu::VertexBufferLayout {
|
||||||
|
array_stride: size_of::<Vertex>() as u64,
|
||||||
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
|
attributes: &[wgpu::VertexAttribute {
|
||||||
|
shader_location: 0,
|
||||||
|
offset: offset_of!(Vertex, screen) as u64,
|
||||||
|
format: wgpu::VertexFormat::Float32x2,
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
let pipeline1 = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
|
label: None,
|
||||||
|
layout: None,
|
||||||
|
vertex: vertex_state.clone(),
|
||||||
|
primitive: wgpu::PrimitiveState {
|
||||||
|
topology: wgpu::PrimitiveTopology::TriangleStrip,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
depth_stencil: None,
|
||||||
|
multisample: wgpu::MultisampleState::default(),
|
||||||
|
fragment: Some(wgpu::FragmentState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: Some("pass_h"),
|
||||||
|
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
|
targets: &[Some(wgpu::ColorTargetState {
|
||||||
|
format,
|
||||||
|
blend: Some(wgpu::BlendState::REPLACE),
|
||||||
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
|
})],
|
||||||
|
}),
|
||||||
|
multiview: None,
|
||||||
|
cache: None,
|
||||||
|
});
|
||||||
|
let pipeline2 = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
|
label: None,
|
||||||
|
layout: None,
|
||||||
|
vertex: vertex_state.clone(),
|
||||||
|
primitive: wgpu::PrimitiveState {
|
||||||
|
topology: wgpu::PrimitiveTopology::TriangleStrip,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
depth_stencil: None,
|
||||||
|
multisample: wgpu::MultisampleState::default(),
|
||||||
|
fragment: Some(wgpu::FragmentState {
|
||||||
|
module: &shader,
|
||||||
|
entry_point: Some("pass_v"),
|
||||||
|
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
|
targets: &[Some(wgpu::ColorTargetState {
|
||||||
|
format,
|
||||||
|
blend: Some(wgpu::BlendState {
|
||||||
|
color: wgpu::BlendComponent {
|
||||||
|
src_factor: wgpu::BlendFactor::One,
|
||||||
|
dst_factor: wgpu::BlendFactor::One,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
alpha: wgpu::BlendComponent {
|
||||||
|
src_factor: wgpu::BlendFactor::One,
|
||||||
|
dst_factor: wgpu::BlendFactor::One,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
|
})],
|
||||||
|
}),
|
||||||
|
multiview: None,
|
||||||
|
cache: None,
|
||||||
|
});
|
||||||
|
Self {
|
||||||
|
view_buf,
|
||||||
|
format,
|
||||||
|
pipeline_h: pipeline1,
|
||||||
|
pipeline_v: pipeline2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(
|
||||||
|
&self,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
source: &wgpu::Texture,
|
||||||
|
// target: &wgpu::Texture,
|
||||||
|
params: Params,
|
||||||
|
) {
|
||||||
|
let target = source;
|
||||||
|
let size = target.size();
|
||||||
|
// assert_eq!(source.size(), size);
|
||||||
|
let intermediate = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: None,
|
||||||
|
size,
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: self.format,
|
||||||
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||||
|
view_formats: &[],
|
||||||
|
});
|
||||||
|
let intermediate = intermediate.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
let params_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: None,
|
||||||
|
contents: bytes_of(¶ms),
|
||||||
|
usage: wgpu::BufferUsages::UNIFORM,
|
||||||
|
});
|
||||||
|
let source = &source.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
let target = &target.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
{
|
||||||
|
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: None,
|
||||||
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
view: &intermediate,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
||||||
|
store: wgpu::StoreOp::Store,
|
||||||
|
},
|
||||||
|
})],
|
||||||
|
depth_stencil_attachment: None,
|
||||||
|
occlusion_query_set: None,
|
||||||
|
timestamp_writes: None,
|
||||||
|
});
|
||||||
|
let bindings = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
label: None,
|
||||||
|
layout: &self.pipeline_h.get_bind_group_layout(0),
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 1,
|
||||||
|
resource: wgpu::BindingResource::TextureView(source),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 2,
|
||||||
|
resource: params_buf.as_entire_binding(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
pass.set_pipeline(&self.pipeline_h);
|
||||||
|
pass.set_vertex_buffer(0, self.view_buf.slice(..));
|
||||||
|
pass.set_bind_group(0, &bindings, &[]);
|
||||||
|
pass.draw(0..4, 0..1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: None,
|
||||||
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
view: target,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
// load: wgpu::LoadOp::Load,
|
||||||
|
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
||||||
|
store: wgpu::StoreOp::Store,
|
||||||
|
},
|
||||||
|
})],
|
||||||
|
depth_stencil_attachment: None,
|
||||||
|
occlusion_query_set: None,
|
||||||
|
timestamp_writes: None,
|
||||||
|
});
|
||||||
|
let params_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: None,
|
||||||
|
contents: bytes_of(¶ms),
|
||||||
|
usage: wgpu::BufferUsages::UNIFORM,
|
||||||
|
});
|
||||||
|
let bindings = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
label: None,
|
||||||
|
layout: &self.pipeline_v.get_bind_group_layout(0),
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 1,
|
||||||
|
resource: wgpu::BindingResource::TextureView(&intermediate),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 2,
|
||||||
|
resource: params_buf.as_entire_binding(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
pass.set_pipeline(&self.pipeline_v);
|
||||||
|
pass.set_vertex_buffer(0, self.view_buf.slice(..));
|
||||||
|
pass.set_bind_group(0, &bindings, &[]);
|
||||||
|
pass.draw(0..4, 0..1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
92
src/glare.wgsl
Normal file
92
src/glare.wgsl
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
struct Params {
|
||||||
|
sigma: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Vertex {
|
||||||
|
@location(0) screen: vec2f,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Varying {
|
||||||
|
@location(0) tex: vec2f,
|
||||||
|
@builtin(position) v: vec4f,
|
||||||
|
}
|
||||||
|
|
||||||
|
@group(0) @binding(1) var tex: texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var<uniform> params: Params;
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn on_vertex(in: Vertex) -> Varying {
|
||||||
|
let uv = in.screen;
|
||||||
|
let xy = vec2(2. * uv.x - 1., 1. - 2. * uv.y);
|
||||||
|
return Varying(uv, vec4(xy, 0., 1.));
|
||||||
|
}
|
||||||
|
|
||||||
|
const CUTOFF: i32 = 200;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn pass_h(in: Varying) -> @location(0) vec4f {
|
||||||
|
let size = vec2i(textureDimensions(tex));
|
||||||
|
let pix = vec2i(floor(in.tex * vec2f(size)));
|
||||||
|
let a = max(0, pix.x - CUTOFF);
|
||||||
|
let b = min(size.x, pix.x + CUTOFF + 1);
|
||||||
|
var accum = vec4(0.);
|
||||||
|
for (var x = a; x < b; x++) {
|
||||||
|
let w = weight(x - pix.x);
|
||||||
|
let pixel = textureLoad(tex, vec2i(x, pix.y), 0);
|
||||||
|
accum += w * pixel;
|
||||||
|
}
|
||||||
|
return vec4(accum.xyz, params.sigma);
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn pass_v(in: Varying) -> @location(0) vec4f {
|
||||||
|
let size = vec2i(textureDimensions(tex));
|
||||||
|
let pix = vec2i(floor(in.tex * vec2f(size)));
|
||||||
|
let a = max(0, pix.y - CUTOFF);
|
||||||
|
let b = min(size.y, pix.y + CUTOFF + 1);
|
||||||
|
var accum = vec4(0.);
|
||||||
|
for (var y = a; y < b; y++) {
|
||||||
|
let w = weight(y - pix.y);
|
||||||
|
let pixel = textureLoad(tex, vec2i(pix.x, y), 0);
|
||||||
|
accum += w * pixel;
|
||||||
|
}
|
||||||
|
return vec4(accum.xyz, params.sigma);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn weight(dist: i32) -> f32 {
|
||||||
|
// let σ = 50.;
|
||||||
|
// let d = f32(dist);
|
||||||
|
// let w = max(0., 1. - abs(d) / σ) / σ;
|
||||||
|
// return .1 * w;
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn weight(dist: i32) -> f32 {
|
||||||
|
let σ = params.sigma / 1e5;
|
||||||
|
let d = f32(dist) / σ;
|
||||||
|
return 3. / (1. + d*d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn weight(dist: i32) -> f32 {
|
||||||
|
// let σ = params.sigma / 1e8;
|
||||||
|
// let d = f32(dist) / σ;
|
||||||
|
// return 3. / (1. + abs(d));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn weight(dist: i32) -> f32 {
|
||||||
|
// let σ = params.sigma / 300.;
|
||||||
|
// let d = abs(f32(dist) / σ);
|
||||||
|
// return 1. / (1. + d*d*d) / σ;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn weight(dist: i32) -> f32 {
|
||||||
|
// let d = f32(abs(dist));
|
||||||
|
// let c = mix(.01, 1., exp(-d*d));
|
||||||
|
// // return c * pow(1.2, -d);
|
||||||
|
// return c / (1. + pow(d, 2.0));
|
||||||
|
// // return .25 * c / (1. + pow(.1 * d, 4.0));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn weight(dist: i32) -> f32 {
|
||||||
|
// let d = 2. * f32(dist);
|
||||||
|
// return exp(-d*d);
|
||||||
|
// }
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod anim;
|
pub mod anim;
|
||||||
|
pub mod glare;
|
||||||
pub mod perlin;
|
pub mod perlin;
|
||||||
pub mod present;
|
pub mod present;
|
||||||
pub mod scene;
|
pub mod scene;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ fn on_vertex(in: Vertex) -> Varying {
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn on_fragment(in: Varying) -> @location(0) vec4f {
|
fn on_fragment(in: Varying) -> @location(0) vec4f {
|
||||||
let pixel = textureSample(tex, smp, in.tex) / params.divisor;
|
let pixel = .1 * textureSample(tex, smp, in.tex) / params.divisor;
|
||||||
return vec4(rational_tone_map(pixel.xyz), 1.0);
|
return vec4(rational_tone_map(pixel.xyz), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ impl Renderer {
|
||||||
trace::Params {
|
trace::Params {
|
||||||
max_reflections: 3,
|
max_reflections: 3,
|
||||||
min_strength: 0.1,
|
min_strength: 0.1,
|
||||||
sphere_count: N_SPHERES,
|
sphere_count: scene.spheres.len() as u32,
|
||||||
seed,
|
seed,
|
||||||
},
|
},
|
||||||
viewport,
|
viewport,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user