Making some comments in the WebGPU rainPass and changing the "effect=none" view to be easier on the eyes.

This commit is contained in:
Rezmason
2021-11-06 15:19:56 -07:00
parent 335ff5ddb7
commit bade1667ad
4 changed files with 27 additions and 14 deletions

View File

@@ -8,6 +8,8 @@ WebGPU
Try to change post processing to compute shaders once they're easier to support Try to change post processing to compute shaders once they're easier to support
std140 std140
Expand it to add array support
Contemplate adding struct support
Document and share it Document and share it

View File

@@ -16,6 +16,7 @@ const cycleStyles = {
const numVerticesPerQuad = 2 * 3; const numVerticesPerQuad = 2 * 3;
const makeConfigBuffer = (device, config, density, gridSize) => { const makeConfigBuffer = (device, config, density, gridSize) => {
// Various effect-related values
const rippleType = config.rippleTypeName in rippleTypes ? rippleTypes[config.rippleTypeName] : -1; const rippleType = config.rippleTypeName in rippleTypes ? rippleTypes[config.rippleTypeName] : -1;
const cycleStyle = config.cycleStyleName in cycleStyles ? cycleStyles[config.cycleStyleName] : 0; const cycleStyle = config.cycleStyleName in cycleStyles ? cycleStyles[config.cycleStyleName] : 0;
const slantVec = [Math.cos(config.slant), Math.sin(config.slant)]; const slantVec = [Math.cos(config.slant), Math.sin(config.slant)];
@@ -178,7 +179,7 @@ export default (context, getInputs) => {
})(); })();
const setSize = (width, height) => { const setSize = (width, height) => {
// Update scene buffer // Update scene buffer: camera and transform math for the volumetric mode
const aspectRatio = width / height; const aspectRatio = width / height;
mat4.perspectiveZO(camera, (Math.PI / 180) * 90, aspectRatio, 0.0001, 1000); mat4.perspectiveZO(camera, (Math.PI / 180) * 90, aspectRatio, 0.0001, 1000);
const screenSize = aspectRatio > 1 ? [1, aspectRatio] : [1 / aspectRatio, 1]; const screenSize = aspectRatio > 1 ? [1, aspectRatio] : [1 / aspectRatio, 1];
@@ -194,6 +195,8 @@ export default (context, getInputs) => {
}); });
const execute = (encoder) => { const execute = (encoder) => {
// We render the code into an FBO using MSDFs: https://github.com/Chlumsky/msdfgen
const computePass = encoder.beginComputePass(); const computePass = encoder.beginComputePass();
computePass.setPipeline(computePipeline); computePass.setPipeline(computePipeline);
computePass.setBindGroup(0, computeBindGroup); computePass.setBindGroup(0, computeBindGroup);

View File

@@ -79,7 +79,7 @@ void main() {
float alpha = clamp(sigDist/fwidth(sigDist) + 0.5, 0.0, 1.0); float alpha = clamp(sigDist/fwidth(sigDist) + 0.5, 0.0, 1.0);
if (showComputationTexture) { if (showComputationTexture) {
gl_FragColor = vec4(glyph.rgb * alpha, 1.0); gl_FragColor = vec4(glyph.rgb - alpha, 1.0);
} else { } else {
gl_FragColor = vec4(vChannel * brightness * alpha, 1.0); gl_FragColor = vec4(vChannel * brightness * alpha, 1.0);
} }

View File

@@ -1,5 +1,8 @@
// This shader module is the star of the show.
// It is where the cell states update and the symbols get drawn to the screen.
[[block]] struct Config { [[block]] struct Config {
// common // common properties used for compute and rendering
animationSpeed : f32; animationSpeed : f32;
glyphSequenceLength : i32; glyphSequenceLength : i32;
glyphTextureColumns : i32; glyphTextureColumns : i32;
@@ -8,7 +11,7 @@
gridSize : vec2<f32>; gridSize : vec2<f32>;
showComputationTexture : i32; showComputationTexture : i32;
// compute // compute-specific properties
brightnessThreshold : f32; brightnessThreshold : f32;
brightnessOverride : f32; brightnessOverride : f32;
brightnessDecay : f32; brightnessDecay : f32;
@@ -25,7 +28,7 @@
cycleStyle : i32; cycleStyle : i32;
rippleType : i32; rippleType : i32;
// render // render-specific properties
forwardSpeed : f32; forwardSpeed : f32;
glyphVerticalSpacing : f32; glyphVerticalSpacing : f32;
glyphEdgeCrop : f32; glyphEdgeCrop : f32;
@@ -36,17 +39,20 @@
volumetric : i32; volumetric : i32;
}; };
// The properties that change over time get their own buffer.
[[block]] struct Time { [[block]] struct Time {
seconds : f32; seconds : f32;
frames : i32; frames : i32;
}; };
// The properties related to the size of the canvas get their own buffer.
[[block]] struct Scene { [[block]] struct Scene {
screenSize : vec2<f32>; screenSize : vec2<f32>;
camera : mat4x4<f32>; camera : mat4x4<f32>;
transform : mat4x4<f32>; transform : mat4x4<f32>;
}; };
// The array of cells that the compute shader updates, and the fragment shader draws.
[[block]] struct CellData { [[block]] struct CellData {
cells: array<vec4<f32>>; cells: array<vec4<f32>>;
}; };
@@ -55,10 +61,10 @@
[[group(0), binding(0)]] var<uniform> config : Config; [[group(0), binding(0)]] var<uniform> config : Config;
[[group(0), binding(1)]] var<uniform> time : Time; [[group(0), binding(1)]] var<uniform> time : Time;
// Compute bindings // Compute-specific bindings
[[group(0), binding(2)]] var<storage, read_write> cells_RW : CellData; [[group(0), binding(2)]] var<storage, read_write> cells_RW : CellData;
// Render bindings // Render-specific bindings
[[group(0), binding(2)]] var<uniform> scene : Scene; [[group(0), binding(2)]] var<uniform> scene : Scene;
[[group(0), binding(3)]] var linearSampler : sampler; [[group(0), binding(3)]] var linearSampler : sampler;
[[group(0), binding(4)]] var msdfTexture : texture_2d<f32>; [[group(0), binding(4)]] var msdfTexture : texture_2d<f32>;
@@ -112,9 +118,7 @@ fn wobble(x : f32) -> f32 {
return x + 0.3 * sin(SQRT_2 * x) + 0.2 * sin(SQRT_5 * x); return x + 0.3 * sin(SQRT_2 * x) + 0.2 * sin(SQRT_5 * x);
} }
// Compute shader // Compute shader core functions
// Core functions
// Rain time is the shader's key underlying concept. // Rain time is the shader's key underlying concept.
// It's why glyphs that share a column are lit simultaneously, and are brighter toward the bottom. // It's why glyphs that share a column are lit simultaneously, and are brighter toward the bottom.
@@ -142,7 +146,7 @@ fn getCycleSpeed(rainTime : f32, brightness : f32) -> f32 {
return config.animationSpeed * config.cycleSpeed * localCycleSpeed; return config.animationSpeed * config.cycleSpeed * localCycleSpeed;
} }
// Additional effects // Compute shader additional effects
fn applySunShowerBrightness(brightness : f32, screenPos : vec2<f32>) -> f32 { fn applySunShowerBrightness(brightness : f32, screenPos : vec2<f32>) -> f32 {
if (brightness >= -4.0) { if (brightness >= -4.0) {
@@ -197,7 +201,7 @@ fn applyCursorEffect(effect : f32, brightness : f32) -> f32 {
return effect; return effect;
} }
// Main function // Compute shader main functions
fn computeResult (isFirstFrame : bool, previousResult : vec4<f32>, glyphPos : vec2<f32>, screenPos : vec2<f32>) -> vec4<f32> { fn computeResult (isFirstFrame : bool, previousResult : vec4<f32>, glyphPos : vec2<f32>, screenPos : vec2<f32>) -> vec4<f32> {
@@ -263,6 +267,7 @@ fn computeResult (isFirstFrame : bool, previousResult : vec4<f32>, glyphPos : ve
[[stage(compute), workgroup_size(32, 1, 1)]] fn computeMain(input : ComputeInput) { [[stage(compute), workgroup_size(32, 1, 1)]] fn computeMain(input : ComputeInput) {
// Resolve the invocation ID to a single cell
var row = i32(input.id.y); var row = i32(input.id.y);
var column = i32(input.id.x); var column = i32(input.id.x);
@@ -272,6 +277,7 @@ fn computeResult (isFirstFrame : bool, previousResult : vec4<f32>, glyphPos : ve
var i = row * i32(config.gridSize.x) + column; var i = row * i32(config.gridSize.x) + column;
// Update the cell
var isFirstFrame = time.frames == 0; var isFirstFrame = time.frames == 0;
var glyphPos = vec2<f32>(f32(column), f32(row)); var glyphPos = vec2<f32>(f32(column), f32(row));
var screenPos = glyphPos / config.gridSize; var screenPos = glyphPos / config.gridSize;
@@ -348,7 +354,7 @@ fn computeResult (isFirstFrame : bool, previousResult : vec4<f32>, glyphPos : ve
); );
} }
// Fragment shader // Fragment shader core functions
fn median3(i : vec3<f32>) -> f32 { fn median3(i : vec3<f32>) -> f32 {
return max(min(i.r, i.g), min(max(i.r, i.g), i.b)); return max(min(i.r, i.g), min(max(i.r, i.g), i.b));
@@ -361,6 +367,8 @@ fn getSymbolUV(glyphCycle : f32) -> vec2<f32> {
return vec2<f32>(f32(symbolX), f32(symbolY)); return vec2<f32>(f32(symbolX), f32(symbolY));
} }
// Fragment shader
[[stage(fragment)]] fn fragMain(input : VertOutput) -> FragOutput { [[stage(fragment)]] fn fragMain(input : VertOutput) -> FragOutput {
var volumetric = bool(config.volumetric); var volumetric = bool(config.volumetric);
@@ -423,7 +431,7 @@ fn getSymbolUV(glyphCycle : f32) -> vec2<f32> {
var output : FragOutput; var output : FragOutput;
if (bool(config.showComputationTexture)) { if (bool(config.showComputationTexture)) {
output.color = vec4<f32>(glyph.rgb * alpha, 1.0); output.color = vec4<f32>(glyph.rgb - alpha, 1.0);
} else { } else {
output.color = vec4<f32>(input.channel * brightness * alpha, 1.0); output.color = vec4<f32>(input.channel * brightness * alpha, 1.0);
} }