Compare commits
No commits in common. "fe998585b4c5fd8749773cf99c818df15c1b1a7c" and "db48a786ac8c033c6d6d4b4f9cf65dac03ecefa8" have entirely different histories.
fe998585b4
...
db48a786ac
|
|
@ -45,10 +45,6 @@ impl SphereParams {
|
||||||
glossiness,
|
glossiness,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deriv(&self, time: f32) -> Vec3 {
|
|
||||||
self.frequencies * self.amplitudes * (self.frequencies * time + self.phases).map(|x| x.cos())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait VecDistribution {
|
trait VecDistribution {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use glam::{mat3, uvec2, vec3, Vec3};
|
use glam::{mat3, uvec2, vec2, vec3, Vec3};
|
||||||
use image::ImageReader;
|
use image::ImageReader;
|
||||||
use present::Presenter;
|
use present::Presenter;
|
||||||
use trace::{Tracer, TracerData, TracerEnv};
|
use trace::{Tracer, TracerData, TracerEnv, Vertex};
|
||||||
use winit::{
|
use winit::{
|
||||||
event::{Event, WindowEvent},
|
event::{Event, WindowEvent},
|
||||||
event_loop::EventLoop,
|
event_loop::EventLoop,
|
||||||
|
|
@ -16,28 +16,24 @@ mod trace;
|
||||||
|
|
||||||
pub use trace::Sphere;
|
pub use trace::Sphere;
|
||||||
|
|
||||||
struct CamLoc {
|
fn make_viewport(eye: Vec3, w: u32, h: u32) -> [Vertex; 4] {
|
||||||
eye: Vec3,
|
|
||||||
forward: Vec3,
|
|
||||||
right: Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_viewport(w: u32, h: u32) -> trace::Viewport {
|
|
||||||
let size = uvec2(w, h).as_vec2();
|
let size = uvec2(w, h).as_vec2();
|
||||||
let size = size.normalize();
|
let size = size.normalize();
|
||||||
trace::Viewport {
|
let (w, h, d) = (size.x, size.y, 1.);
|
||||||
corner: vec3(size.x, size.y, 1.),
|
let screen_coord = [vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)];
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert_location(cam: CamLoc) -> trace::CameraLocation {
|
let up = Vec3::Z;
|
||||||
let fwd = cam.forward.normalize();
|
let fwd = -eye.normalize();
|
||||||
let up = cam.right.cross(fwd).normalize();
|
let right = eye.cross(up).normalize();
|
||||||
let right = up.cross(fwd).normalize();
|
let up = eye.cross(right).normalize();
|
||||||
trace::CameraLocation {
|
let m = mat3(fwd, right, up);
|
||||||
eye: cam.eye,
|
|
||||||
view: mat3(right, up, fwd),
|
let world_coord = [vec3(d, -w, -h), vec3(d, w, -h), vec3(d, -w, h), vec3(d, w, h)];
|
||||||
}
|
[0, 1, 2, 3].map(|k| Vertex {
|
||||||
|
eye,
|
||||||
|
world: eye + m * (world_coord[k]),
|
||||||
|
screen: screen_coord[k],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const N_SPHERES: u32 = 100;
|
const N_SPHERES: u32 = 100;
|
||||||
|
|
@ -57,7 +53,7 @@ fn main() {
|
||||||
|
|
||||||
let output_format = wgpu::TextureFormat::Bgra8UnormSrgb;
|
let output_format = wgpu::TextureFormat::Bgra8UnormSrgb;
|
||||||
let hdr_format = wgpu::TextureFormat::Rgba16Float;
|
let hdr_format = wgpu::TextureFormat::Rgba16Float;
|
||||||
let tracer = Tracer::new(&device, hdr_format);
|
let mut tracer = Tracer::new(&device, hdr_format);
|
||||||
let mut rng = rand_pcg::Pcg32::new(42, 0);
|
let mut rng = rand_pcg::Pcg32::new(42, 0);
|
||||||
let sphere_params: Vec<_> = {
|
let sphere_params: Vec<_> = {
|
||||||
let distr = anim::distr();
|
let distr = anim::distr();
|
||||||
|
|
@ -65,14 +61,6 @@ fn main() {
|
||||||
};
|
};
|
||||||
let camera_params = {
|
let camera_params = {
|
||||||
let mut p = anim::distr()(&mut rng);
|
let mut p = anim::distr()(&mut rng);
|
||||||
p.amplitudes *= 2.0;
|
|
||||||
p.frequencies *= 0.1;
|
|
||||||
p
|
|
||||||
};
|
|
||||||
let target_params = {
|
|
||||||
let mut p = anim::distr()(&mut rng);
|
|
||||||
p.origin = Vec3::splat(0.0);
|
|
||||||
p.amplitudes *= 0.5;
|
|
||||||
p.frequencies *= 0.1;
|
p.frequencies *= 0.1;
|
||||||
p
|
p
|
||||||
};
|
};
|
||||||
|
|
@ -143,11 +131,8 @@ fn main() {
|
||||||
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);
|
let time = frame as f32 / (60. * RAYS_PER_PIXEL as f32);
|
||||||
let eye = camera_params.to_sphere(time).center;
|
let camera_pos = camera_params.to_sphere(time).center;
|
||||||
let right = camera_params.deriv(time);
|
tracer.set_view(&queue, &make_viewport(camera_pos, size.width, size.height));
|
||||||
let forward = target_params.to_sphere(time).center - eye;
|
|
||||||
let viewport = make_viewport(size.width, size.height);
|
|
||||||
let location = convert_location(CamLoc { eye, forward, right });
|
|
||||||
let spheres: Vec<_> = sphere_params.iter().map(|p| p.to_sphere(time)).collect();
|
let spheres: Vec<_> = sphere_params.iter().map(|p| p.to_sphere(time)).collect();
|
||||||
let data = TracerData::new(&device, &tracer, &spheres);
|
let data = TracerData::new(&device, &tracer, &spheres);
|
||||||
tracer.render(
|
tracer.render(
|
||||||
|
|
@ -160,12 +145,6 @@ fn main() {
|
||||||
sphere_count: N_SPHERES,
|
sphere_count: N_SPHERES,
|
||||||
seed: frame,
|
seed: frame,
|
||||||
},
|
},
|
||||||
viewport,
|
|
||||||
trace::Aperture {
|
|
||||||
radius: 0.001,
|
|
||||||
focal_distance: std::f32::INFINITY,
|
|
||||||
},
|
|
||||||
location,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -223,7 +202,7 @@ async fn init_gpu(wnd: &Window) -> Result<(wgpu::Device, wgpu::Queue, wgpu::Surf
|
||||||
label: None,
|
label: None,
|
||||||
required_features: wgpu::Features::PUSH_CONSTANTS,
|
required_features: wgpu::Features::PUSH_CONSTANTS,
|
||||||
required_limits: wgpu::Limits {
|
required_limits: wgpu::Limits {
|
||||||
max_push_constant_size: 128,
|
max_push_constant_size: 32,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
memory_hints: Default::default(),
|
memory_hints: Default::default(),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::mem;
|
use std::mem::{self, offset_of};
|
||||||
|
|
||||||
use bytemuck::{bytes_of, cast_slice, Pod, Zeroable};
|
use bytemuck::{bytes_of, cast_slice, Pod, Zeroable};
|
||||||
use glam::{vec2, Mat3, Vec2, Vec3};
|
use glam::{Vec2, Vec3};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||||
|
|
@ -13,57 +13,6 @@ pub struct Params {
|
||||||
pub seed: u32,
|
pub seed: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct Viewport {
|
|
||||||
pub corner: Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Aperture {
|
|
||||||
pub radius: f32,
|
|
||||||
pub focal_distance: f32, // from 0 (exclusive) to +∞ (inclusive)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct CameraLocation {
|
|
||||||
pub eye: Vec3,
|
|
||||||
pub view: Mat3,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
|
||||||
#[repr(C)]
|
|
||||||
struct ParamsData {
|
|
||||||
params: Params,
|
|
||||||
camera: CameraData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
|
||||||
#[repr(C)]
|
|
||||||
struct CameraData {
|
|
||||||
u: Vec3,
|
|
||||||
width: f32,
|
|
||||||
v: Vec3,
|
|
||||||
height: f32,
|
|
||||||
w: Vec3,
|
|
||||||
aperture: f32,
|
|
||||||
eye: Vec3,
|
|
||||||
antifocal: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(Viewport, CameraLocation, Aperture)> for CameraData {
|
|
||||||
fn from(value: (Viewport, CameraLocation, Aperture)) -> Self {
|
|
||||||
CameraData {
|
|
||||||
u: value.1.view.x_axis,
|
|
||||||
v: value.1.view.y_axis,
|
|
||||||
w: value.1.view.z_axis,
|
|
||||||
eye: value.1.eye,
|
|
||||||
width: value.0.corner.x / value.0.corner.z,
|
|
||||||
height: value.0.corner.y / value.0.corner.z,
|
|
||||||
aperture: value.2.radius,
|
|
||||||
antifocal: 1. / value.2.focal_distance,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Sphere {
|
pub struct Sphere {
|
||||||
pub center: Vec3,
|
pub center: Vec3,
|
||||||
|
|
@ -75,7 +24,9 @@ pub struct Sphere {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct Vertex {
|
pub struct Vertex {
|
||||||
|
pub eye: Vec3,
|
||||||
|
pub world: Vec3,
|
||||||
pub screen: Vec2,
|
pub screen: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,19 +41,6 @@ struct SphereData {
|
||||||
glossiness: f32,
|
glossiness: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Sphere> for SphereData {
|
|
||||||
fn from(s: &Sphere) -> Self {
|
|
||||||
SphereData {
|
|
||||||
center: s.center,
|
|
||||||
radius: s.radius,
|
|
||||||
emit_color: s.emit_color,
|
|
||||||
pad1: 0.0,
|
|
||||||
reflect_color: s.reflect_color,
|
|
||||||
glossiness: s.glossiness,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Tracer {
|
pub struct Tracer {
|
||||||
view_buf: wgpu::Buffer,
|
view_buf: wgpu::Buffer,
|
||||||
pipeline: wgpu::RenderPipeline,
|
pipeline: wgpu::RenderPipeline,
|
||||||
|
|
@ -120,11 +58,11 @@ static SHADER: &str = include_str!("trace.wgsl");
|
||||||
|
|
||||||
impl Tracer {
|
impl Tracer {
|
||||||
pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self {
|
pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self {
|
||||||
let screen_coord = [vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)];
|
let view_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
let view_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: None,
|
label: None,
|
||||||
contents: cast_slice(&screen_coord),
|
size: (4 * mem::size_of::<Vertex>()) as u64,
|
||||||
usage: wgpu::BufferUsages::VERTEX,
|
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||||
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
|
|
@ -169,7 +107,7 @@ impl Tracer {
|
||||||
bind_group_layouts: &[&spheres_bgl, &envmap_bgl],
|
bind_group_layouts: &[&spheres_bgl, &envmap_bgl],
|
||||||
push_constant_ranges: &[wgpu::PushConstantRange {
|
push_constant_ranges: &[wgpu::PushConstantRange {
|
||||||
stages: wgpu::ShaderStages::FRAGMENT,
|
stages: wgpu::ShaderStages::FRAGMENT,
|
||||||
range: 0..mem::size_of::<ParamsData>() as u32,
|
range: 0..16,
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
|
|
@ -182,11 +120,23 @@ impl Tracer {
|
||||||
buffers: &[wgpu::VertexBufferLayout {
|
buffers: &[wgpu::VertexBufferLayout {
|
||||||
array_stride: size_of::<Vertex>() as u64,
|
array_stride: size_of::<Vertex>() as u64,
|
||||||
step_mode: wgpu::VertexStepMode::Vertex,
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
attributes: &[wgpu::VertexAttribute {
|
attributes: &[
|
||||||
shader_location: 0,
|
wgpu::VertexAttribute {
|
||||||
offset: 0,
|
shader_location: 0,
|
||||||
format: wgpu::VertexFormat::Float32x2,
|
offset: offset_of!(Vertex, eye) as u64,
|
||||||
}],
|
format: wgpu::VertexFormat::Float32x3,
|
||||||
|
},
|
||||||
|
wgpu::VertexAttribute {
|
||||||
|
shader_location: 1,
|
||||||
|
offset: offset_of!(Vertex, world) as u64,
|
||||||
|
format: wgpu::VertexFormat::Float32x3,
|
||||||
|
},
|
||||||
|
wgpu::VertexAttribute {
|
||||||
|
shader_location: 2,
|
||||||
|
offset: offset_of!(Vertex, screen) as u64,
|
||||||
|
format: wgpu::VertexFormat::Float32x2,
|
||||||
|
},
|
||||||
|
],
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
primitive: wgpu::PrimitiveState {
|
primitive: wgpu::PrimitiveState {
|
||||||
|
|
@ -226,25 +176,13 @@ impl Tracer {
|
||||||
Self { view_buf, pipeline }
|
Self { view_buf, pipeline }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(
|
pub fn set_view(&mut self, queue: &wgpu::Queue, vertices: &[Vertex; 4]) {
|
||||||
&self,
|
queue.write_buffer(&self.view_buf, 0, bytes_of(vertices));
|
||||||
pass: &mut wgpu::RenderPass,
|
}
|
||||||
data: &TracerData,
|
|
||||||
env: &TracerEnv,
|
pub fn render(&self, pass: &mut wgpu::RenderPass, data: &TracerData, env: &TracerEnv, params: Params) {
|
||||||
params: Params,
|
|
||||||
viewport: Viewport,
|
|
||||||
aperture: Aperture,
|
|
||||||
camera: CameraLocation,
|
|
||||||
) {
|
|
||||||
pass.set_pipeline(&self.pipeline);
|
pass.set_pipeline(&self.pipeline);
|
||||||
pass.set_push_constants(
|
pass.set_push_constants(wgpu::ShaderStages::FRAGMENT, 0, bytes_of(¶ms));
|
||||||
wgpu::ShaderStages::FRAGMENT,
|
|
||||||
0,
|
|
||||||
bytes_of(&ParamsData {
|
|
||||||
params,
|
|
||||||
camera: (viewport, camera, aperture).into(),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
pass.set_vertex_buffer(0, self.view_buf.slice(..));
|
pass.set_vertex_buffer(0, self.view_buf.slice(..));
|
||||||
pass.set_bind_group(0, &data.bindings, &[]);
|
pass.set_bind_group(0, &data.bindings, &[]);
|
||||||
pass.set_bind_group(1, &env.bindings, &[]);
|
pass.set_bind_group(1, &env.bindings, &[]);
|
||||||
|
|
@ -254,7 +192,17 @@ impl Tracer {
|
||||||
|
|
||||||
impl TracerData {
|
impl TracerData {
|
||||||
pub fn new(device: &wgpu::Device, tracer: &Tracer, spheres: &[Sphere]) -> Self {
|
pub fn new(device: &wgpu::Device, tracer: &Tracer, spheres: &[Sphere]) -> Self {
|
||||||
let spheres: Vec<_> = spheres.iter().map(SphereData::from).collect();
|
let spheres: Vec<_> = spheres
|
||||||
|
.iter()
|
||||||
|
.map(|s| SphereData {
|
||||||
|
center: s.center,
|
||||||
|
radius: s.radius,
|
||||||
|
emit_color: s.emit_color,
|
||||||
|
pad1: 0.0,
|
||||||
|
reflect_color: s.reflect_color,
|
||||||
|
glossiness: s.glossiness,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
let spheres_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let spheres_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
contents: cast_slice(&spheres),
|
contents: cast_slice(&spheres),
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,6 @@ struct Params {
|
||||||
min_strength: f32,
|
min_strength: f32,
|
||||||
sphere_count: i32,
|
sphere_count: i32,
|
||||||
seed: u32,
|
seed: u32,
|
||||||
|
|
||||||
right: vec3f,
|
|
||||||
width: f32,
|
|
||||||
up: vec3f,
|
|
||||||
height: f32,
|
|
||||||
forward: vec3f,
|
|
||||||
aperture: f32,
|
|
||||||
eye: vec3f,
|
|
||||||
antifocal: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Sphere {
|
struct Sphere {
|
||||||
|
|
@ -23,11 +14,14 @@ struct Sphere {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
@location(0) screen: vec2f,
|
@location(0) eye: vec3f,
|
||||||
|
@location(1) world: vec3f,
|
||||||
|
@location(2) screen: vec2f,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Varying {
|
struct Varying {
|
||||||
@location(0) dir: vec3f,
|
@location(0) eye: vec3f,
|
||||||
|
@location(1) world: vec3f,
|
||||||
@builtin(position) screen: vec4f,
|
@builtin(position) screen: vec4f,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,13 +32,12 @@ var<push_constant> params: Params;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn on_vertex(in: Vertex) -> Varying {
|
fn on_vertex(in: Vertex) -> Varying {
|
||||||
let m = mat3x3(params.width * params.right, params.height * params.up, params.forward);
|
return Varying(in.eye, in.world, vec4(in.screen, 0.0, 1.0));
|
||||||
return Varying(m * vec3(in.screen, 1.0), vec4(in.screen, 0.0, 1.0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn on_fragment(in: Varying) -> @location(0) vec4f {
|
fn on_fragment(in: Varying) -> @location(0) vec4f {
|
||||||
return vec4(trace_fragment(in), 1.);
|
return trace_fragment(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sqr(v: vec3f) -> f32 {
|
fn sqr(v: vec3f) -> f32 {
|
||||||
|
|
@ -70,19 +63,15 @@ fn to_sphere(center: vec3f, radius: f32, t: ptr<function, f32>) -> bool {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_fragment(in: Varying) -> vec3f {
|
fn trace_fragment(in: Varying) -> vec4f {
|
||||||
seed(in.screen);
|
seed(in.screen);
|
||||||
|
|
||||||
var result = vec3(0.);
|
var result = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
var color = vec3(1.);
|
var color = vec3(1.0, 1.0, 1.0);
|
||||||
let view_mtx = mat3x3(params.right, params.up, params.forward);
|
pos = in.eye;
|
||||||
let aperture_offset_rel = params.aperture * rand_disc();
|
|
||||||
let aperture_offset_abs = view_mtx * vec3(aperture_offset_rel, 0.);
|
|
||||||
pos = params.eye + aperture_offset_abs;
|
|
||||||
let off_px = vec2(rand_float(), rand_float()) - .5;
|
let off_px = vec2(rand_float(), rand_float()) - .5;
|
||||||
let off_w = mat2x3(dpdx(in.dir), dpdy(in.dir));
|
let off_w = mat2x3(dpdx(in.world), dpdy(in.world));
|
||||||
let dir = in.dir + off_w * off_px;
|
ray = normalize(in.world + off_w * off_px - in.eye);
|
||||||
ray = normalize(dir - params.antifocal * aperture_offset_abs);
|
|
||||||
|
|
||||||
for (var k = 0; k < params.max_reflections; k++) {
|
for (var k = 0; k < params.max_reflections; k++) {
|
||||||
var sphere = -1;
|
var sphere = -1;
|
||||||
|
|
@ -96,24 +85,17 @@ fn trace_fragment(in: Varying) -> vec3f {
|
||||||
}
|
}
|
||||||
if (sphere == -1) {
|
if (sphere == -1) {
|
||||||
let env = textureSampleLevel(env_texture, env_sampler, ray, 0.0);
|
let env = textureSampleLevel(env_texture, env_sampler, ray, 0.0);
|
||||||
result += 3.0 * color * env.xyz;
|
result += vec4(3.0 * color * env.xyz, 0.0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let s = spheres[sphere];
|
let s = spheres[sphere];
|
||||||
pos += t * ray;
|
pos += t * ray;
|
||||||
let normal = (pos - s.center) / s.radius;
|
let normal = (pos - s.center) / s.radius;
|
||||||
if (all(s.emit_color == vec3(0.))) {
|
result += vec4(color * s.emit_color, 0.0);
|
||||||
color *= s.reflect_color;
|
color *= s.reflect_color;
|
||||||
let diffuse = normal + rand_sphere();
|
let diffuse = normal + rand_sphere();
|
||||||
let specular = reflect(ray, normal);
|
let specular = reflect(ray, normal);
|
||||||
ray = normalize(mix(diffuse, specular, s.glossiness));
|
ray = normalize(mix(diffuse, specular, s.glossiness));
|
||||||
} else {
|
|
||||||
let d = dot(-ray, normal);
|
|
||||||
let strength = d * d; // it would be 1 for surface emission, but this models volume emission
|
|
||||||
result += color * s.emit_color * strength;
|
|
||||||
color *= (1. - strength);
|
|
||||||
pos += 1e-3 * ray;
|
|
||||||
}
|
|
||||||
if (length(color) < params.min_strength) {
|
if (length(color) < params.min_strength) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -146,16 +128,6 @@ fn rand_float() -> f32 {
|
||||||
return f32(rand_next()) / 0x1p32;
|
return f32(rand_next()) / 0x1p32;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rand_disc() -> vec2f {
|
|
||||||
for (var k = 0; k < 16; k++) {
|
|
||||||
let v = vec2f(rand_float(), rand_float()) - 0.5;
|
|
||||||
if (length(v) <= 0.5) {
|
|
||||||
return 2. * v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return vec2f(0.0); // safeguard
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rand_sphere() -> vec3f {
|
fn rand_sphere() -> vec3f {
|
||||||
for (var k = 0; k < 16; k++) {
|
for (var k = 0; k < 16; k++) {
|
||||||
let v = vec3f(rand_float(), rand_float(), rand_float()) - 0.5;
|
let v = vec3f(rand_float(), rand_float(), rand_float()) - 0.5;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user