Skip to content

Commit

Permalink
2d light propagation: Just improve everything and separate the scene
Browse files Browse the repository at this point in the history
  • Loading branch information
s-macke committed Sep 30, 2023
1 parent 4b44ff9 commit e4f348b
Show file tree
Hide file tree
Showing 7 changed files with 385 additions and 140 deletions.
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
set -e
npm install
#npm install
npm run prestart:copysrc
npm run prestart:copyassets
npx tsc -noEmit
Expand Down
78 changes: 43 additions & 35 deletions src/scripts/light/aces-tone-mapping.wgsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ACES tonemapper
fn ACES(x: vec3<f32>) -> vec3<f32> {
fn ACES(x: vec3f) -> vec3f {
const a: f32 = 2.51;
const b: f32 = .03;
const c: f32 = 2.43;
Expand All @@ -24,22 +24,22 @@ const ACESOutputMat = mat3x3f(
-0.00327, -0.07276, 1.07602
);

fn RRTAndODTFit(v: vec3<f32>) -> vec3<f32> {
let a: vec3<f32> = v * (v + 0.0245786) - 0.000090537;
let b: vec3<f32> = v * (0.983729 * v + 0.4329510) + 0.238081;
fn RRTAndODTFit(v: vec3f) -> vec3f {
let a: vec3f = v * (v + 0.0245786) - 0.000090537;
let b: vec3f = v * (0.983729 * v + 0.4329510) + 0.238081;
return a / b;
}

fn ACESFitted(_color: vec3<f32>) -> vec3<f32> {
var color: vec3<f32> = _color * ACESInputMat;
fn ACESFitted(_color: vec3f) -> vec3f {
var color: vec3f = _color * ACESInputMat;

// Apply RRT and ODT
color = RRTAndODTFit(color);

color = color * ACESOutputMat;

// Clamp to [0, 1]
color = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
color = clamp(color, vec3f(0.0), vec3f(1.0));

return color;
}
Expand All @@ -50,16 +50,16 @@ fn linear_srgb(x: f32) -> f32 {
return mix(1.055*pow(x, 1./2.4) - 0.055, 12.92*x, step(x,0.0031308));
}

fn linear_srgb_vec(x: vec3<f32>) -> vec3<f32> {
return mix(1.055*pow(x, vec3(1./2.4)) - 0.055, 12.92*x, step(x,vec3(0.0031308)));
fn linear_srgb_vec(x: vec3f) -> vec3f {
return mix(1.055*pow(x, vec3f(1./2.4)) - 0.055, 12.92*x, step(x,vec3f(0.0031308)));
}

fn srgb_linear(x: f32) -> f32 {
return mix(pow((x + 0.055)/1.055,2.4), x / 12.92, step(x,0.04045));
}

fn srgb_linear_vec(x: vec3<f32>) -> vec3<f32> {
return mix(pow((x + 0.055)/1.055,vec3(2.4)), x / 12.92, step(x,vec3(0.04045)));
fn srgb_linear_vec(x: vec3f) -> vec3f {
return mix(pow((x + 0.055)/1.055,vec3f(2.4)), x / 12.92, step(x,vec3f(0.04045)));
}
/*
struct SD {
Expand All @@ -69,8 +69,8 @@ struct SD {
};
*/

fn shade2(sh: vec3<f32>, dV: vec3<f32>, sd: SD, ch: i32) -> f32 {
let dZ = vec3<f32>(0., 0., 1.) * CH_Basis;
fn shade2(sh: vec3f, dV: vec3f, sd: SD, ch: i32) -> f32 {
let dZ = vec3f(0., 0., 1.) * CH_Basis;
let W: f32 = max(0.0, dot(sh, dZ));
var L: f32 = max(0.0, dot(sh, dV));

Expand All @@ -90,48 +90,56 @@ fn shade2(sh: vec3<f32>, dV: vec3<f32>, sd: SD, ch: i32) -> f32 {
}

@group(0) @binding(0) var texture: texture_2d_array<f32>;
//@group(0) @binding(1) var texture_signed_distance: texture_2d<f32>;
@group(0) @binding(1) var scene: texture_2d_array<f32>;

fn getMap(p: vec2i) -> SD {
let data: vec4f = textureLoad(scene, p, 4, 0);
if ((data.r < 0.) || (data.g < 0.) || (data.b < 0.)) {
return SD(data.a, -data.rgb, true);
} else {
return SD(data.a, data.rgb, false);
}
}


struct VertexOutput {
@builtin(position) Position : vec4<f32>,
@location(0) fragUV : vec2<f32>
@builtin(position) Position : vec4f,
@location(0) fragUV : vec2f
};

@fragment
fn main(data: VertexOutput) -> @location(0) vec4<f32> {
var iResolution: vec2<f32> = vec2<f32>(textureDimensions(texture, 0));

//setup_mouse_pos();
fn main(data: VertexOutput) -> @location(0) vec4f {
var iResolution = vec2f(textureDimensions(texture, 0));
set_resolution(iResolution);

var uv: vec2<f32> = data.fragUV * 2.0 - 1.0;
uv *= vec2<f32>(iResolution.x/iResolution.y, 1.0);
let p = vec2i(data.fragUV*iResolution);

var uv: vec2f = data.fragUV * 2.0 - 1.0;
uv *= vec2f(iResolution.x/iResolution.y, 1.0);

//let tuv: vec2<f32> = ((uv * vec2<f32>(iResolution.y/iResolution.x,1.0))*0.5 + 0.5);
let shr: vec3<f32> = textureLoad(texture, vec2<i32>(data.fragUV*iResolution), 0, 0).xyz;
let shg: vec3<f32> = textureLoad(texture, vec2<i32>(data.fragUV*iResolution), 1, 0).xyz;
let shb: vec3<f32> = textureLoad(texture, vec2<i32>(data.fragUV*iResolution), 2, 0).xyz;
let shr: vec3f = textureLoad(texture, p, 0, 0).xyz;
let shg: vec3f = textureLoad(texture, p, 1, 0).xyz;
let shb: vec3f = textureLoad(texture, p, 2, 0).xyz;

//var dV: vec3<f32> = vec3<f32>(-normal_map(uv, pixel_radius), 1.) * CH_Basis;
//var dV: vec3<f32> = vec3<f32>(-n, 1.) * CH_Basis;
//dV = sh_irradiance_probe(dV);
var dV: vec3<f32> = lambert(-normal_map(uv, pixel_radius)) * CH_Basis;

let sd: SD = map(uv);
//let sd = SD(2.5, vec3<f32>(0.), false);
let sd: SD = getMap(p);
let n: vec2f = textureLoad(scene, p, 3, 0).xy; // normal of surface
var dV: vec3f = lambert(-n) * CH_Basis;

let col = vec3<f32>(
let col = vec3f(
shade2(shr, dV, sd, 0),
shade2(shg, dV, sd, 1),
shade2(shb, dV, sd, 2));

//let col = vec3<f32>(shr.z, shg.z, shb.z)*CH_Basis.z;
let fragColor = vec4(linear_srgb_vec(ACESFitted(max(col, vec3(0.0)))), 1.0);
let fragColor = vec4f(linear_srgb_vec(ACESFitted(max(col, vec3f(0.0)))), 1.0);

//let c = textureLoad(myTexture, vec2<i32>(data.fragUV*d), 0).rgb;
//var fragColor = vec4<f32>(pow( clamp(c, vec3<f32>(0.), vec3<f32>(1.)), vec3<f32>(1. / 2.2)), 1.);
//let fragColor = vec4<f32>(ACES(sd.albedo), 1.0);
//fragColor = vec4<f32>(sd.d, -sd.d, sd.d, 1.0);
//fragColor = vec4<f32>(shr.r, shr.r, shr.r, 1.0);
//var fragColor = vec4f(pow( clamp(c, vec3<f32>(0.), vec3<f32>(1.)), vec3<f32>(1. / 2.2)), 1.);
//let fragColor = vec4f(ACES(sd.albedo), 1.0);
return fragColor;
// return textureLoad(texture_signed_distance, vec2<i32>(data.fragUV*iResolution), 0).rgba;
}
6 changes: 3 additions & 3 deletions src/scripts/light/distance.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn rotate(p: vec2<f32>, r: f32) -> vec2<f32> {
// shaded distance
struct SD {
d : f32,
albedo: vec3<f32>,
albedo: vec3f,
emissive: bool
};

Expand Down Expand Up @@ -54,11 +54,11 @@ fn sphere(p: vec2<f32>, r: f32) -> f32 {

fn slitlight(p: vec2<f32>) -> SD {
const color: vec3<f32> = vec3(0.01, 0.5, 0.95);
var angle : f32 = max(0.0,cos(atan2(p.y, p.x)*6.0));
var angle : f32 = max(0.0, cos(atan2(p.y, p.x)*6.0));
if (angle < 0.5) {
angle = 0.0;
}
let d2: SD = emitter(sphere(p, 0.1),color * angle * 20.0);
let d2: SD = emitter(sphere(p, 0.1), color * angle * 20.0);
return d2;
}

Expand Down
61 changes: 40 additions & 21 deletions src/scripts/light/light.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,23 @@ import {Texture} from "../webgpu/texture";
import {Buffer} from "../webgpu/buffer";
import {GPUAbstractRunner, RunnerType} from "../AbstractGPURunner";
import {Render} from "../render/render";
import {LightScene} from "./scene/scene";
import {ShowError} from "../ui";

export class LightPropagation extends GPUAbstractRunner {
width: number
height: number

render: Render
scene: LightScene

textureDest: Texture
textureSrc: Texture

bind_group_layout: GPUBindGroupLayout
bind_group: GPUBindGroup
scene_bind_group_layout: GPUBindGroupLayout
scene_bind_group: GPUBindGroup
pipeline_layout: GPUPipelineLayout
compute_pipeline: GPUComputePipeline
shader: GPUProgrammableStage
Expand All @@ -47,15 +52,24 @@ export class LightPropagation extends GPUAbstractRunner {

async Init() {
console.log("Create Texture")

this.textureDest = GPU.CreateStorageTextureArray(this.width, this.height, 3, "rgba16float")
this.textureSrc = GPU.CreateStorageTextureArray(this.width, this.height, 3, "rgba16float")

this.stagingBuffer = GPU.CreateUniformBuffer(4 * 4) // must be a multiple of 16 bytes
this.stagingData = new Float32Array(4)

this.scene = new LightScene(this.stagingBuffer)
try {
await this.scene.Init()
} catch (e) {
ShowError("Creation of Scene failed", e as Error)
throw e
}

console.log("Create Render")
this.render = new Render(
[this.textureDest],
[this.textureDest, this.scene.emitter],
"scripts/light/common.wgsl", "scripts/light/distance.wgsl", "scripts/light/aces-tone-mapping.wgsl")
await this.render.Init()

Expand All @@ -75,7 +89,7 @@ export class LightPropagation extends GPUAbstractRunner {
visibility: GPUShaderStage.COMPUTE,
storageTexture: {
access: "write-only",
format: "rgba16float",
format: this.textureDest.format,
viewDimension: "2d-array"
}
}, {
Expand All @@ -84,15 +98,7 @@ export class LightPropagation extends GPUAbstractRunner {
buffer: {
type: "uniform"
}
}/*, {
binding: 3,
visibility: GPUShaderStage.COMPUTE,
texture: {sampleType: "unfilterable-float"}
}, {
binding: 4,
visibility: GPUShaderStage.COMPUTE,
sampler: {}
}*/]
}]
})

this.bind_group = GPU.device.createBindGroup({
Expand All @@ -106,18 +112,31 @@ export class LightPropagation extends GPUAbstractRunner {
}, {
binding: 2,
resource: this.stagingBuffer.resource
}/*, {
binding: 7,
resource: this.textureSignedDistance.textureView
}, {
binding: 8,
resource: GPU.CreateSampler()
}*/]
}]
})

this.scene_bind_group_layout = GPU.device.createBindGroupLayout({
entries: [
{
binding: 0,
visibility: GPUShaderStage.COMPUTE,
texture: {
sampleType: "unfilterable-float",
viewDimension: "2d-array"
}
}]
})

this.scene_bind_group = GPU.device.createBindGroup({
layout: this.scene_bind_group_layout,
entries: [{
binding: 0,
resource: this.scene.emitter.textureView
}]
})

this.pipeline_layout = GPU.device.createPipelineLayout({
bindGroupLayouts: [this.bind_group_layout]
bindGroupLayouts: [this.bind_group_layout, this.scene_bind_group_layout]
})

this.compute_pipeline = GPU.device.createComputePipeline({
Expand All @@ -137,6 +156,7 @@ export class LightPropagation extends GPUAbstractRunner {
for(let i = 0; i < 40; i++) {
let pass: GPUComputePassEncoder = encoder.beginComputePass();
pass.setBindGroup(0, this.bind_group);
pass.setBindGroup(1, this.scene_bind_group);
pass.setPipeline(this.compute_pipeline);
pass.dispatchWorkgroups(this.width / 8, this.height / 8);
pass.end();
Expand All @@ -150,8 +170,7 @@ export class LightPropagation extends GPUAbstractRunner {
}

async Run() {
//GPU.device.queue.submit([this.GetCommandBuffer()]);
GPU.device.queue.submit([this.GetCommandBuffer(), this.render.getCommandBuffer()]);
GPU.device.queue.submit([this.scene.GetCommandBuffer(), this.GetCommandBuffer(), this.render.getCommandBuffer()]);
await GPU.device.queue.onSubmittedWorkDone();
}

Expand Down
Loading

0 comments on commit e4f348b

Please sign in to comment.