Skip to content

Commit

Permalink
2d light propagation: Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
s-macke committed Sep 19, 2023
1 parent 07adc18 commit dccb97c
Showing 1 changed file with 61 additions and 66 deletions.
127 changes: 61 additions & 66 deletions src/scripts/light/propagate.wgsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
struct StagingBuffer {
iMouse: vec2<f32>,
iMouse: vec2f,
wheel: f32,
iFrame: f32
};
Expand All @@ -12,14 +12,14 @@ struct StagingBuffer {
@group(0) @binding(5) var img_outputB: texture_storage_2d<rgba32float, write>;
@group(0) @binding(6) var<uniform> staging: StagingBuffer;

fn occluder(p: vec2<i32>, sd: ptr<function, SD>) -> vec3<f32> {
let uv: vec2<f32> = pixel2uv(p);
fn occluder(p: vec2i, sd: ptr<function, SD>) -> vec3f {
let uv: vec2f = pixel2uv(p);
*sd = map(uv);
let d: f32 = (*sd).d / pixel_radius;
if (d > 1.0) {
return vec3<f32>(0.0);
return vec3f(0.0);
}
let n: vec2<f32> = normal_map(uv, pixel_radius);
let n: vec2f = normal_map(uv, pixel_radius);
// orthodox: solid angle goes from 100% to 50%, then drops
// to 0% when the point is inside the surface
//float opacity = step(0.0,d)*(d*0.5+0.5);
Expand All @@ -37,12 +37,12 @@ fn occluder(p: vec2<i32>, sd: ptr<function, SD>) -> vec3<f32> {
// sd: signed distance to neighbor
// colorChannel: which color channel to propagate
// img_input: input image
fn propagate(p: vec2<i32>, n: vec2<f32>, sa: f32, sd: SD,
outchr: ptr<function, vec3<f32>>,
outchg: ptr<function, vec3<f32>>,
outchb: ptr<function, vec3<f32>>) {
fn propagate(p: vec2i, n: vec2f, sa: f32, sd: SD,
outchr: ptr<function, vec3f>,
outchg: ptr<function, vec3f>,
outchb: ptr<function, vec3f>) {

let R: vec2<i32> = vec2<i32>(resolution.xy);
let R = vec2i(resolution.xy);

// check if neighbor is out of bounds. if so, return black
if ((p.x < 0) || (p.y < 0) || (p.x >= R.x) || (p.y >= R.y)) {
Expand All @@ -58,87 +58,82 @@ fn propagate(p: vec2<i32>, n: vec2<f32>, sa: f32, sd: SD,
var occ_sd: SD;
var occ: vec3<f32> = occluder(p, &occ_sd);

let Fr: vec3<f32> = textureLoad(img_inputR, p, 0).xyz; // incoming red light from neighbor as circular harmonics
let Fg: vec3<f32> = textureLoad(img_inputG, p, 0).xyz; // incoming green light from neighbor as circular harmonics
let Fb: vec3<f32> = textureLoad(img_inputB, p, 0).xyz; // incoming blue light from neighbor as circular harmonics
let Fr: vec3f = textureLoad(img_inputR, p, 0).xyz; // incoming red light from neighbor as circular harmonics
let Fg: vec3f = textureLoad(img_inputG, p, 0).xyz; // incoming green light from neighbor as circular harmonics
let Fb: vec3f = textureLoad(img_inputB, p, 0).xyz; // incoming blue light from neighbor as circular harmonics

let dV = vec3<f32>(n, 1.) * CH_Basis;
let dV = vec3f(n, 1.) * CH_Basis;

// light hitting our interior cell wall
let Lr: f32 = max(0.0, dot(Fr, dV * sa));
let Lg: f32 = max(0.0, dot(Fg, dV * sa));
let Lb: f32 = max(0.0, dot(Fb, dV * sa));
let L = max(vec3f(0.0), vec3f(
dot(Fr, dV * sa),
dot(Fg, dV * sa),
dot(Fb, dV * sa)));

// how much of their cell wall is occupied?
let E: f32 = max(0.0, dot(occ, dV * sa));
let O: f32 = min(E, 1.0); // do bounce

// subtract occluder from light
let chr: vec3<f32> = dV * Lr * (1.0 - O);
let chg: vec3<f32> = dV * Lg * (1.0 - O);
let chb: vec3<f32> = dV * Lb * (1.0 - O);
let chr: vec3f = dV * (L.r * (1.0 - O));
let chg: vec3f = dV * (L.g * (1.0 - O));
let chb: vec3f = dV * (L.b * (1.0 - O));

let dRV = vec3<f32>(-n, 1.) * CH_Basis;
var ref2r = 0.0;
var ref2g = 0.0;
var ref2b = 0.0;
let dRV = vec3f(-n, 1.) * CH_Basis;

var ref2 = vec3f(0.0);
if (sd.emissive) {
if (abs(occ_sd.d) <= pixel_radius) {
ref2r = sd.albedo.r * E;
ref2g = sd.albedo.g * E;
ref2b = sd.albedo.b * E;
ref2 = sd.albedo * E;
}
} else {
ref2r = O * Lr * sd.albedo.r;
ref2g = O * Lg * sd.albedo.g;
ref2b = O * Lb * sd.albedo.b;
ref2 = O * L * sd.albedo;
}
// add emission
*outchr += chr + ref2r * dRV;
*outchg += chg + ref2g * dRV;
*outchb += chb + ref2b * dRV;
*outchr += chr + ref2.r * dRV;
*outchg += chg + ref2.g * dRV;
*outchb += chb + ref2.b * dRV;
}

fn solid_angle(a: vec2<f32>, b: vec2<f32>) -> f32 {
fn solid_angle(a: vec2f, b: vec2f) -> f32 {
return acos(dot(normalize(a), normalize(b)));
}

fn lpv_kernel(fragCoord: vec2<i32>,
outchr: ptr<function, vec3<f32>>,
outchg: ptr<function, vec3<f32>>,
outchb: ptr<function, vec3<f32>>) {
fn lpv_kernel(fragCoord: vec2i,
outchr: ptr<function, vec3f>,
outchg: ptr<function, vec3f>,
outchb: ptr<function, vec3f>) {

let p: vec2<i32> = fragCoord;
let p: vec2i = fragCoord;
var sd: SD = map(pixel2uv(p));

//#define PROPAGATE(OFS, N, SA) propagate(channel, p + OFS, N, SA, sd, ch)
let d: i32 = 1;
let x: f32 = 2.0;
let sa1: f32 = solid_angle(vec2<f32>(x, -1.0), vec2<f32>(x, 1.0)); // ~53.13°, projecting to the right side of our pixel
let sa2: f32 = solid_angle(vec2<f32>(x-1.0, 1.0), vec2<f32>(x, 1.0)); // ~18.43°, projecting to the top/bottom side of our pixel
let sa1: f32 = solid_angle(vec2f(x, -1.0), vec2<f32>(x, 1.0)); // ~53.13°, projecting to the right side of our pixel
let sa2: f32 = solid_angle(vec2f(x-1.0, 1.0), vec2<f32>(x, 1.0)); // ~18.43°, projecting to the top/bottom side of our pixel
// note that sa2 = (90° - sa1) / 2
let dn1: vec2<f32> = normalize(vec2<f32>(x - 0.5, 1.0)); // normal to the center of the top side of our pixel
let dn0: vec2<f32> = normalize(vec2<f32>(x - 0.5, -1.0)); // normal to the center of the bottom side of our pixel
let dn1: vec2f = normalize(vec2f(x - 0.5, 1.0)); // normal to the center of the top side of our pixel
let dn0: vec2f = normalize(vec2f(x - 0.5, -1.0)); // normal to the center of the bottom side of our pixel

var chr: vec3<f32>;
var chg: vec3<f32>;
var chb: vec3<f32>;
propagate(p+vec2<i32>(-1, 0), vec2<f32>(1., 0.), sa1, sd, &chr, &chg, &chb);
propagate(p+vec2<i32>(-1, 0), dn1, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2<i32>(-1, 0), dn0, sa2, sd, &chr, &chg, &chb);
var chr: vec3f;
var chg: vec3f;
var chb: vec3f;
propagate(p+vec2i(-1, 0), vec2f(1., 0.), sa1, sd, &chr, &chg, &chb);
propagate(p+vec2i(-1, 0), dn1, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2i(-1, 0), dn0, sa2, sd, &chr, &chg, &chb);

propagate(p+vec2<i32>( 1, 0), vec2<f32>(-1., 0.), sa1, sd, &chr, &chg, &chb);
propagate(p+vec2<i32>( 1, 0), -dn0, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2<i32>( 1, 0), -dn1, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2i( 1, 0), vec2f(-1., 0.), sa1, sd, &chr, &chg, &chb);
propagate(p+vec2i( 1, 0), -dn0, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2i( 1, 0), -dn1, sa2, sd, &chr, &chg, &chb);

propagate(p+vec2<i32>(0, -1), vec2<f32>(0., 1.), sa1, sd, &chr, &chg, &chb);
propagate(p+vec2<i32>(0, -1), dn1.yx, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2<i32>(0, -1), dn0.yx, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2i(0, -1), vec2f(0., 1.), sa1, sd, &chr, &chg, &chb);
propagate(p+vec2i(0, -1), dn1.yx, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2i(0, -1), dn0.yx, sa2, sd, &chr, &chg, &chb);

propagate(p+vec2<i32>(0, 1), vec2<f32>(0., -1.), sa1, sd, &chr, &chg, &chb);
propagate(p+vec2<i32>(0, 1), -dn1.yx, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2<i32>(0, 1), -dn0.yx, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2i(0, 1), vec2f(0., -1.), sa1, sd, &chr, &chg, &chb);
propagate(p+vec2i(0, 1), -dn1.yx, sa2, sd, &chr, &chg, &chb);
propagate(p+vec2i(0, 1), -dn0.yx, sa2, sd, &chr, &chg, &chb);

*outchr = chr;
*outchg = chg;
Expand All @@ -147,21 +142,21 @@ fn lpv_kernel(fragCoord: vec2<i32>,

@compute @workgroup_size(8, 8)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
let iResolution: vec2<f32> = vec2<f32>(textureDimensions(img_inputR, 0));
let iResolution: vec2f = vec2f(textureDimensions(img_inputR, 0));

mouse_pos = ((staging.iMouse.xy / iResolution.xy)*2.0 - 1.0) * vec2(iResolution.x/iResolution.y, 1.0);
mouse_wheel = staging.wheel;

set_resolution(iResolution.xy);

var chr = vec3<f32>(0.);
var chg = vec3<f32>(0.);
var chb = vec3<f32>(0.);
var chr = vec3f(0.);
var chg = vec3f(0.);
var chb = vec3f(0.);

lpv_kernel(vec2<i32>(global_id.xy), &chr, &chg, &chb);
textureStore(img_outputR, vec2<i32>(global_id.xy), vec4<f32>(chr, 0.));
textureStore(img_outputG, vec2<i32>(global_id.xy), vec4<f32>(chg, 0.));
textureStore(img_outputB, vec2<i32>(global_id.xy), vec4<f32>(chb, 0.));
lpv_kernel(vec2i(global_id.xy), &chr, &chg, &chb);
textureStore(img_outputR, vec2i(global_id.xy), vec4f(chr, 0.));
textureStore(img_outputG, vec2i(global_id.xy), vec4f(chg, 0.));
textureStore(img_outputB, vec2i(global_id.xy), vec4f(chb, 0.));
}


0 comments on commit dccb97c

Please sign in to comment.