From c82a1c380399e7dbb3450b7840dc1200d2439637 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 5 Jan 2025 01:46:37 +0300 Subject: [PATCH 1/3] A simple postprocessing glare --- src/bin/minitracer/main.rs | 34 ++++-- src/glare.rs | 210 +++++++++++++++++++++++++++++++++++++ src/glare.wgsl | 65 ++++++++++++ src/lib.rs | 1 + src/scene.rs | 2 - src/trace.rs | 6 -- src/trace.wgsl | 9 -- 7 files changed, 304 insertions(+), 23 deletions(-) create mode 100644 src/glare.rs create mode 100644 src/glare.wgsl diff --git a/src/bin/minitracer/main.rs b/src/bin/minitracer/main.rs index 4310b7e..3485a69 100644 --- a/src/bin/minitracer/main.rs +++ b/src/bin/minitracer/main.rs @@ -1,6 +1,7 @@ use std::error::Error; -use glam::uvec2; +use glam::{uvec2, vec2}; +use raytracing3::glare::Glarer; use raytracing3::present::{self, Presenter}; use raytracing3::scene::{load_envmap, Renderer, SceneParams}; use winit::{ @@ -28,6 +29,7 @@ fn main() { let hdr_format = wgpu::TextureFormat::Rgba16Float; let scene = SceneParams::new(N_SPHERES); let renderer = Renderer::new(&device, envmap); + let glarer = Glarer::new(&device, hdr_format); let presenter = Presenter::new(&device, output_format); let mut frame = 0; @@ -63,7 +65,7 @@ fn main() { let output = surface.get_current_texture().unwrap(); let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); let size = output.texture.size(); - let hdr = device.create_texture(&wgpu::TextureDescriptor { + let hdr1 = device.create_texture(&wgpu::TextureDescriptor { label: None, size, mip_level_count: 1, @@ -73,13 +75,13 @@ fn main() { usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, view_formats: &[], }); - let hdr = hdr.create_view(&wgpu::TextureViewDescriptor::default()); + let hdr1 = hdr1.create_view(&wgpu::TextureViewDescriptor::default()); 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, &hdr1); + let time = frame as f32 / (60. * RAYS_PER_PIXEL as f32); for _ in 0..RAYS_PER_PIXEL { frame += 1; - let time = frame as f32 / (60. * RAYS_PER_PIXEL as f32); renderer.render_frame( &device, &mut render_pass, @@ -90,10 +92,30 @@ fn main() { ); } } + let hdr2 = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: hdr_format, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: &[], + }); + let hdr2 = hdr2.create_view(&wgpu::TextureViewDescriptor::default()); + let sigma = 3000. / vec2(size.width as f32, size.height as f32).length(); + glarer.render( + &device, + &mut encoder, + uvec2(size.width, size.height), + &hdr1, + &hdr2, + raytracing3::glare::Params { sigma }, + ); presenter.render( &device, &mut encoder, - &hdr, + &hdr2, &view, present::Params { divisor: RAYS_PER_PIXEL as f32, diff --git a/src/glare.rs b/src/glare.rs new file mode 100644 index 0000000..f1d7cd1 --- /dev/null +++ b/src/glare.rs @@ -0,0 +1,210 @@ +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::() 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::REPLACE), + 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, + size: UVec2, + source: &wgpu::TextureView, + target: &wgpu::TextureView, + params: Params, + ) { + let intermediate = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size: wgpu::Extent3d { + width: size.x, + height: size.y, + depth_or_array_layers: 1, + }, + 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 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::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); + } + } +} diff --git a/src/glare.wgsl b/src/glare.wgsl new file mode 100644 index 0000000..86653e0 --- /dev/null +++ b/src/glare.wgsl @@ -0,0 +1,65 @@ +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; +@group(0) @binding(2) var 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 = 1000; + +@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 { +// if (dist == 0) { +// return 1.0; +// } + let σ = params.sigma; + let d = σ * f32(dist); +// let w = exp(-0.5 * d*d / (σ*σ)) / (2.5 * σ); +// return 0.1 * w; + return .33 * σ / (1. + d*d); +} diff --git a/src/lib.rs b/src/lib.rs index dfaedd1..83f62ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod anim; +pub mod glare; pub mod perlin; pub mod present; pub mod scene; diff --git a/src/scene.rs b/src/scene.rs index a9fc038..a35f7b1 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -125,8 +125,6 @@ impl Renderer { trace::Aperture { radius: 0.0003, focal_distance: std::f32::INFINITY, - glare_strength: 0.1, - glare_radius: 0.1, }, location, ); diff --git a/src/trace.rs b/src/trace.rs index e276e2e..6bd0277 100644 --- a/src/trace.rs +++ b/src/trace.rs @@ -22,8 +22,6 @@ pub struct Viewport { pub struct Aperture { pub radius: f32, pub focal_distance: f32, // from 0 (exclusive) to +∞ (inclusive) - pub glare_strength: f32, - pub glare_radius: f32, // at distance 1 } #[derive(Debug, Clone, Copy)] @@ -50,8 +48,6 @@ struct CameraData { aperture: f32, eye: Vec3, antifocal: f32, - glare_strength: f32, - glare_radius: f32, } impl From<(Viewport, CameraLocation, Aperture)> for CameraData { @@ -65,8 +61,6 @@ impl From<(Viewport, CameraLocation, Aperture)> for CameraData { height: value.0.corner.y / value.0.corner.z, aperture: value.2.radius, antifocal: 1. / value.2.focal_distance, - glare_strength: value.2.glare_strength, - glare_radius: value.2.glare_radius, } } } diff --git a/src/trace.wgsl b/src/trace.wgsl index 727b320..698cb44 100644 --- a/src/trace.wgsl +++ b/src/trace.wgsl @@ -12,9 +12,6 @@ struct Params { aperture: f32, eye: vec3f, antifocal: f32, - - glare_strength: f32, - glare_radius: f32, } struct Sphere { @@ -85,12 +82,6 @@ fn trace_fragment(in: Varying) -> vec3f { let off_px = vec2(rand_float(), rand_float()) - .5; let off_w = mat2x3(dpdx(in.dir), dpdy(in.dir)); var dir = in.dir + off_w * off_px; - if (rand_float() < params.glare_strength) { - let p = rand_float(); - let d = params.glare_radius * pow(p, 2.); - let glare_off = d * rand_disc(); - dir += view_mtx * vec3(glare_off, 0.); - } ray = normalize(dir - params.antifocal * aperture_offset_abs); for (var k = 0; k < params.max_reflections; k++) { From 973c505f0c4f1b59e8cdaead88ef5264ff84e83e Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 5 Jan 2025 02:36:27 +0300 Subject: [PATCH 2/3] Some more glare stuff --- src/bin/minitracer/main.rs | 30 ++++++------------------------ src/glare.rs | 30 +++++++++++++++++++++--------- src/glare.wgsl | 34 +++++++++++++++++++++++++--------- 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/bin/minitracer/main.rs b/src/bin/minitracer/main.rs index 3485a69..f741366 100644 --- a/src/bin/minitracer/main.rs +++ b/src/bin/minitracer/main.rs @@ -65,7 +65,7 @@ fn main() { let output = surface.get_current_texture().unwrap(); let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); let size = output.texture.size(); - let hdr1 = device.create_texture(&wgpu::TextureDescriptor { + let hdr = device.create_texture(&wgpu::TextureDescriptor { label: None, size, mip_level_count: 1, @@ -75,10 +75,10 @@ fn main() { usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, view_formats: &[], }); - let hdr1 = hdr1.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 render_pass = renderer.prepare(&mut encoder, &hdr1); + 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 { frame += 1; @@ -92,30 +92,12 @@ fn main() { ); } } - let hdr2 = device.create_texture(&wgpu::TextureDescriptor { - label: None, - size, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: hdr_format, - usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, - view_formats: &[], - }); - let hdr2 = hdr2.create_view(&wgpu::TextureViewDescriptor::default()); - let sigma = 3000. / vec2(size.width as f32, size.height as f32).length(); - glarer.render( - &device, - &mut encoder, - uvec2(size.width, size.height), - &hdr1, - &hdr2, - raytracing3::glare::Params { sigma }, - ); + let sigma = vec2(size.width as f32, size.height as f32).length(); + glarer.render(&device, &mut encoder, &hdr, raytracing3::glare::Params { sigma }); presenter.render( &device, &mut encoder, - &hdr2, + &hdr1v, &view, present::Params { divisor: RAYS_PER_PIXEL as f32, diff --git a/src/glare.rs b/src/glare.rs index f1d7cd1..7d6882a 100644 --- a/src/glare.rs +++ b/src/glare.rs @@ -89,7 +89,18 @@ impl Glarer { compilation_options: wgpu::PipelineCompilationOptions::default(), targets: &[Some(wgpu::ColorTargetState { format, - blend: Some(wgpu::BlendState::REPLACE), + 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, })], }), @@ -108,18 +119,16 @@ impl Glarer { &self, device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, - size: UVec2, - source: &wgpu::TextureView, - target: &wgpu::TextureView, + 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: wgpu::Extent3d { - width: size.x, - height: size.y, - depth_or_array_layers: 1, - }, + size, mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, @@ -133,6 +142,8 @@ impl Glarer { 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, @@ -174,6 +185,7 @@ impl Glarer { view: target, resolve_target: None, ops: wgpu::Operations { + // load: wgpu::LoadOp::Load, load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), store: wgpu::StoreOp::Store, }, diff --git a/src/glare.wgsl b/src/glare.wgsl index 86653e0..325445c 100644 --- a/src/glare.wgsl +++ b/src/glare.wgsl @@ -21,7 +21,7 @@ fn on_vertex(in: Vertex) -> Varying { return Varying(uv, vec4(xy, 0., 1.)); } -const CUTOFF: i32 = 1000; +const CUTOFF: i32 = 10000; @fragment fn pass_h(in: Varying) -> @location(0) vec4f { @@ -53,13 +53,29 @@ fn pass_v(in: Varying) -> @location(0) vec4f { 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 / 3000.; +// let d = f32(dist) / σ; +// return .1 / (1. + d*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 { -// if (dist == 0) { -// return 1.0; -// } - let σ = params.sigma; - let d = σ * f32(dist); -// let w = exp(-0.5 * d*d / (σ*σ)) / (2.5 * σ); -// return 0.1 * w; - return .33 * σ / (1. + d*d); + 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)); } From 60f648cfb9f82428dc802c443778cb65b4ebfb71 Mon Sep 17 00:00:00 2001 From: numzero Date: Mon, 6 Jan 2025 02:13:06 +0300 Subject: [PATCH 3/3] This works as kinda glare but... not really --- src/glare.wgsl | 31 +++++++++++++++++++++---------- src/present.wgsl | 2 +- src/scene.rs | 11 +++++++++-- src/trace.wgsl | 3 ++- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/glare.wgsl b/src/glare.wgsl index 325445c..066db36 100644 --- a/src/glare.wgsl +++ b/src/glare.wgsl @@ -21,7 +21,7 @@ fn on_vertex(in: Vertex) -> Varying { return Varying(uv, vec4(xy, 0., 1.)); } -const CUTOFF: i32 = 10000; +const CUTOFF: i32 = 200; @fragment fn pass_h(in: Varying) -> @location(0) vec4f { @@ -60,10 +60,16 @@ fn pass_v(in: Varying) -> @location(0) vec4f { // 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 / 3000.; +// let σ = params.sigma / 1e8; // let d = f32(dist) / σ; -// return .1 / (1. + d*d) / σ; +// return 3. / (1. + abs(d)); // } // fn weight(dist: i32) -> f32 { @@ -72,10 +78,15 @@ fn pass_v(in: Varying) -> @location(0) vec4f { // 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 = 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); +// } diff --git a/src/present.wgsl b/src/present.wgsl index 2a7412f..2ea9789 100644 --- a/src/present.wgsl +++ b/src/present.wgsl @@ -24,7 +24,7 @@ fn on_vertex(in: Vertex) -> Varying { @fragment 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); } diff --git a/src/scene.rs b/src/scene.rs index a35f7b1..4a77100 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -109,7 +109,14 @@ impl Renderer { let forward = target - eye; let viewport = make_viewport(size.x, size.y); let location = convert_location(CamLoc { eye, forward, right }); - let spheres: Vec<_> = scene.spheres.iter().map(|p| p.to_sphere(time)).collect(); + let mut spheres: Vec<_> = scene.spheres.iter().map(|p| p.to_sphere(time)).collect(); + spheres.push(crate::Sphere { + center: vec3(0., 215e3, 0.), + radius: 1e3, + emit_color: Vec3::splat(1.0e6), + reflect_color: Vec3::splat(0.), + glossiness: 0., + }); let data = TracerData::new(&device, &self.tracer, &spheres); self.tracer.render( &mut render_pass.0, @@ -118,7 +125,7 @@ impl Renderer { trace::Params { max_reflections: 3, min_strength: 0.1, - sphere_count: N_SPHERES, + sphere_count: spheres.len() as u32, seed, }, viewport, diff --git a/src/trace.wgsl b/src/trace.wgsl index 698cb44..1872aea 100644 --- a/src/trace.wgsl +++ b/src/trace.wgsl @@ -96,7 +96,8 @@ fn trace_fragment(in: Varying) -> vec3f { } if (sphere == -1) { let env = textureSampleLevel(env_texture, env_sampler, ray, 0.0); - result += 3.0 * color * env.xyz; +// result += (vec3(5.0) + 0.001 * env.xyz) * color; + result += 5.0 * env.xyz * color; break; } let s = spheres[sphere];