mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-18 14:19:30 -07:00
Fixing several embarrassing bugs.
WebGPU and REGL projects now flipY again, and they properly flip the symbolY glyph coordinate in the rain pass's fragment shader. Switching on some older code that was disabled for FF Nightly support— it makes more sense to wait for that support as implementations finalize. Added mipmap to images loaded into REGL project.
This commit is contained in:
17
TODO.txt
17
TODO.txt
@@ -1,6 +1,17 @@
|
|||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
Seems like bloom size and resolution impact the REGL and WebGPU bloom implementations differently
|
Seems like bloom size and resolution impact the REGL and WebGPU bloom implementations differently
|
||||||
|
Ossify the REGL bloom
|
||||||
|
Load all the GLSL from files
|
||||||
|
Move high pass into WebGPU bloom
|
||||||
|
|
||||||
|
Live config update roadmap
|
||||||
|
|
||||||
|
Write an explanation of the rain pass (and include images)
|
||||||
|
Compute
|
||||||
|
Volumetric quads
|
||||||
|
Fullscreen quad and spacial mapping
|
||||||
|
MSDFs
|
||||||
|
|
||||||
Audio system
|
Audio system
|
||||||
Toggle (or number representing frequency)
|
Toggle (or number representing frequency)
|
||||||
@@ -37,12 +48,6 @@ WebGPU
|
|||||||
|
|
||||||
Improve loop support
|
Improve loop support
|
||||||
|
|
||||||
Write an explanation of the rain pass (and include images)
|
|
||||||
Compute
|
|
||||||
Volumetric quads
|
|
||||||
Fullscreen quad and spacial mapping
|
|
||||||
MSDFs
|
|
||||||
|
|
||||||
Idea: Build a UI
|
Idea: Build a UI
|
||||||
Replace versions with presets
|
Replace versions with presets
|
||||||
Simple changes update the values
|
Simple changes update the values
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { loadImage, loadText, makePassFBO, makePass } from "./utils.js";
|
import { loadText, makePassFBO, makePass } from "./utils.js";
|
||||||
|
|
||||||
let start;
|
let start;
|
||||||
const numClicks = 5;
|
const numClicks = 5;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { loadImage, loadText, makePassFBO, makePass } from "./utils.js";
|
import { loadText, makePassFBO, makePass } from "./utils.js";
|
||||||
|
|
||||||
// Multiplies the rendered rain and bloom by a loaded in image
|
// Multiplies the rendered rain and bloom by a loaded in image
|
||||||
|
|
||||||
|
|||||||
@@ -134,8 +134,8 @@ export default ({ regl, config, lkg }) => {
|
|||||||
// We render the code into an FBO using MSDFs: https://github.com/Chlumsky/msdfgen
|
// We render the code into an FBO using MSDFs: https://github.com/Chlumsky/msdfgen
|
||||||
const glyphMSDF = loadImage(regl, config.glyphMSDFURL);
|
const glyphMSDF = loadImage(regl, config.glyphMSDFURL);
|
||||||
const glintMSDF = loadImage(regl, config.glintMSDFURL);
|
const glintMSDF = loadImage(regl, config.glintMSDFURL);
|
||||||
const baseTexture = loadImage(regl, config.baseTextureURL);
|
const baseTexture = loadImage(regl, config.baseTextureURL, true);
|
||||||
const glintTexture = loadImage(regl, config.glintTextureURL);
|
const glintTexture = loadImage(regl, config.glintTextureURL, true);
|
||||||
const rainPassVert = loadText("shaders/glsl/rainPass.vert.glsl");
|
const rainPassVert = loadText("shaders/glsl/rainPass.vert.glsl");
|
||||||
const rainPassFrag = loadText("shaders/glsl/rainPass.frag.glsl");
|
const rainPassFrag = loadText("shaders/glsl/rainPass.frag.glsl");
|
||||||
const output = makePassFBO(regl, config.useHalfFloat);
|
const output = makePassFBO(regl, config.useHalfFloat);
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
const makePassTexture = (regl, halfFloat, mipmap) =>
|
const makePassTexture = (regl, halfFloat) =>
|
||||||
regl.texture({
|
regl.texture({
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
type: halfFloat ? "half float" : "uint8",
|
type: halfFloat ? "half float" : "uint8",
|
||||||
wrap: "clamp",
|
wrap: "clamp",
|
||||||
minFilter: "mipmap",
|
min: "linear",
|
||||||
min: mipmap ? "mipmap" : "linear",
|
|
||||||
mag: "linear",
|
mag: "linear",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -26,7 +25,9 @@ const makeDoubleBuffer = (regl, props) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadImage = (regl, url) => {
|
const isPowerOfTwo = (x) => Math.log2(x) % 1 == 0;
|
||||||
|
|
||||||
|
const loadImage = (regl, url, mipmap) => {
|
||||||
let texture = regl.texture([[0]]);
|
let texture = regl.texture([[0]]);
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
return {
|
return {
|
||||||
@@ -55,10 +56,17 @@ const loadImage = (regl, url) => {
|
|||||||
data.src = url;
|
data.src = url;
|
||||||
await data.decode();
|
await data.decode();
|
||||||
loaded = true;
|
loaded = true;
|
||||||
|
if (mipmap) {
|
||||||
|
if (!isPowerOfTwo(data.width) || !isPowerOfTwo(data.height)) {
|
||||||
|
console.warn(`Can't mipmap a non-power-of-two image: ${url}`);
|
||||||
|
}
|
||||||
|
mipmap = false;
|
||||||
|
}
|
||||||
texture = regl.texture({
|
texture = regl.texture({
|
||||||
data,
|
data,
|
||||||
mag: "linear",
|
mag: "linear",
|
||||||
min: "linear",
|
min: mipmap ? "mipmap" : "linear",
|
||||||
|
flipY: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})(),
|
})(),
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
/*
|
|
||||||
// TODO: switch back to this impl once it doesn't break on FF Nightly
|
|
||||||
|
|
||||||
const loadTexture = async (device, url) => {
|
const loadTexture = async (device, url) => {
|
||||||
|
if (url == null) {
|
||||||
|
return device.createTexture({
|
||||||
|
size: [1, 1, 1],
|
||||||
|
format: "rgba8unorm",
|
||||||
|
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const data = await response.blob();
|
const data = await response.blob();
|
||||||
const source = await createImageBitmap(data);
|
const source = await createImageBitmap(data);
|
||||||
@@ -13,42 +18,7 @@ const loadTexture = async (device, url) => {
|
|||||||
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
|
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
|
||||||
});
|
});
|
||||||
|
|
||||||
device.queue.copyExternalImageToTexture({ source }, { texture }, size);
|
device.queue.copyExternalImageToTexture({ source, flipY: true }, { texture }, size);
|
||||||
|
|
||||||
return texture;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
const loadTexture = async (device, url) => {
|
|
||||||
if (url == null) {
|
|
||||||
return device.createTexture({
|
|
||||||
size: [1, 1, 1],
|
|
||||||
format: "rgba8unorm",
|
|
||||||
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const image = new Image();
|
|
||||||
image.crossOrigin = "Anonymous";
|
|
||||||
image.src = url;
|
|
||||||
await image.decode();
|
|
||||||
const { width, height } = image;
|
|
||||||
const size = [width, height, 1];
|
|
||||||
|
|
||||||
const canvas = document.createElement("canvas");
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
const ctx = canvas.getContext("2d");
|
|
||||||
ctx.drawImage(image, 0, 0);
|
|
||||||
const source = ctx.getImageData(0, 0, width, height).data;
|
|
||||||
|
|
||||||
const texture = device.createTexture({
|
|
||||||
size,
|
|
||||||
format: "rgba8unorm",
|
|
||||||
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
|
|
||||||
});
|
|
||||||
|
|
||||||
device.queue.writeTexture({ texture }, source, { bytesPerRow: 4 * width }, size);
|
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -102,13 +102,13 @@ vec3 getBrightness(vec4 raindrop, vec4 effect, float quadDepth, vec2 uv) {
|
|||||||
vec2 getSymbolUV(float index) {
|
vec2 getSymbolUV(float index) {
|
||||||
float symbolX = modI(index, glyphTextureGridSize.x);
|
float symbolX = modI(index, glyphTextureGridSize.x);
|
||||||
float symbolY = (index - symbolX) / glyphTextureGridSize.x;
|
float symbolY = (index - symbolX) / glyphTextureGridSize.x;
|
||||||
|
symbolY = glyphTextureGridSize.y - symbolY - 1.;
|
||||||
return vec2(symbolX, symbolY);
|
return vec2(symbolX, symbolY);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 getSymbol(vec2 uv, float index) {
|
vec2 getSymbol(vec2 uv, float index) {
|
||||||
// resolve UV to cropped position of glyph in MSDF texture
|
// resolve UV to cropped position of glyph in MSDF texture
|
||||||
uv = fract(uv * vec2(numColumns, numRows));
|
uv = fract(uv * vec2(numColumns, numRows));
|
||||||
uv.y = 1.0 - uv.y; // y-flip
|
|
||||||
uv -= 0.5;
|
uv -= 0.5;
|
||||||
uv *= clamp(1. - glyphEdgeCrop, 0., 1.);
|
uv *= clamp(1. - glyphEdgeCrop, 0., 1.);
|
||||||
uv += 0.5;
|
uv += 0.5;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ fn getBrightness(uv : vec2<f32>) -> vec4<f32> {
|
|||||||
|
|
||||||
var uv = vec2<f32>(coord) / vec2<f32>(screenSize);
|
var uv = vec2<f32>(coord) / vec2<f32>(screenSize);
|
||||||
|
|
||||||
var bgColor = textureSampleLevel( backgroundTex, linearSampler, uv, 0.0 ).rgb;
|
var bgColor = textureSampleLevel( backgroundTex, linearSampler, vec2<f32>(uv.x, 1.0 - uv.y), 0.0 ).rgb;
|
||||||
|
|
||||||
// Combine the texture and bloom, then blow it out to reveal more of the image
|
// Combine the texture and bloom, then blow it out to reveal more of the image
|
||||||
var brightness = getBrightness(uv);
|
var brightness = getBrightness(uv);
|
||||||
|
|||||||
@@ -352,11 +352,10 @@ fn computeEffect (simTime : f32, isFirstFrame : bool, glyphPos : vec2<f32>, scre
|
|||||||
|
|
||||||
// Vertex shader
|
// Vertex shader
|
||||||
|
|
||||||
// Firefox Nightly (that is to say, Naga) currently has a bug that mixes up these values from ones in the uniforms.
|
var<private> quadCorners : array<vec2<f32>, NUM_VERTICES_PER_QUAD> = array<vec2<f32>, NUM_VERTICES_PER_QUAD>(
|
||||||
// var<private> quadCorners : array<vec2<f32>, NUM_VERTICES_PER_QUAD> = array<vec2<f32>, NUM_VERTICES_PER_QUAD>(
|
vec2<f32>(0.0, 0.0), vec2<f32>(0.0, 1.0), vec2<f32>(1.0, 1.0),
|
||||||
// vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 0.0), vec2<f32>(0.0, 1.0),
|
vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0), vec2<f32>(1.0, 0.0)
|
||||||
// vec2<f32>(1.0, 1.0), vec2<f32>(0.0, 1.0), vec2<f32>(1.0, 0.0)
|
);
|
||||||
// );
|
|
||||||
|
|
||||||
@vertex fn vertMain(input : VertInput) -> VertOutput {
|
@vertex fn vertMain(input : VertInput) -> VertOutput {
|
||||||
|
|
||||||
@@ -368,8 +367,7 @@ fn computeEffect (simTime : f32, isFirstFrame : bool, glyphPos : vec2<f32>, scre
|
|||||||
var i = i32(input.index);
|
var i = i32(input.index);
|
||||||
var quadIndex = i / NUM_VERTICES_PER_QUAD;
|
var quadIndex = i / NUM_VERTICES_PER_QUAD;
|
||||||
|
|
||||||
// var quadCorner = quadCorners[i % NUM_VERTICES_PER_QUAD];
|
var quadCorner = quadCorners[i % NUM_VERTICES_PER_QUAD];
|
||||||
var quadCorner = vec2<f32>(f32(i % 2), f32((i + 1) % 6 / 3));
|
|
||||||
|
|
||||||
var quadPosition = vec2<f32>(
|
var quadPosition = vec2<f32>(
|
||||||
f32(quadIndex % i32(quadGridSize.x)),
|
f32(quadIndex % i32(quadGridSize.x)),
|
||||||
@@ -487,13 +485,13 @@ fn getBrightness(raindrop : vec4<f32>, effect : vec4<f32>, uv : vec2<f32>, quadD
|
|||||||
fn getSymbolUV(symbol : i32) -> vec2<f32> {
|
fn getSymbolUV(symbol : i32) -> vec2<f32> {
|
||||||
var symbolX = symbol % config.glyphTextureGridSize.x;
|
var symbolX = symbol % config.glyphTextureGridSize.x;
|
||||||
var symbolY = symbol / config.glyphTextureGridSize.x;
|
var symbolY = symbol / config.glyphTextureGridSize.x;
|
||||||
|
symbolY = config.glyphTextureGridSize.y - symbolY - 1;
|
||||||
return vec2<f32>(f32(symbolX), f32(symbolY));
|
return vec2<f32>(f32(symbolX), f32(symbolY));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getSymbol(cellUV : vec2<f32>, index : i32) -> vec2<f32> {
|
fn getSymbol(cellUV : vec2<f32>, index : i32) -> vec2<f32> {
|
||||||
// resolve UV to cropped position of glyph in MSDF texture
|
// resolve UV to cropped position of glyph in MSDF texture
|
||||||
var uv = fract(cellUV * config.gridSize);
|
var uv = fract(cellUV * config.gridSize);
|
||||||
uv.y = 1.0 - uv.y; // y-flip
|
|
||||||
uv -= 0.5;
|
uv -= 0.5;
|
||||||
uv *= clamp(1.0 - config.glyphEdgeCrop, 0.0, 1.0);
|
uv *= clamp(1.0 - config.glyphEdgeCrop, 0.0, 1.0);
|
||||||
uv += 0.5;
|
uv += 0.5;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ fn getBrightness(uv : vec2<f32>) -> vec4<f32> {
|
|||||||
|
|
||||||
var uv = vec2<f32>(coord) / vec2<f32>(screenSize);
|
var uv = vec2<f32>(coord) / vec2<f32>(screenSize);
|
||||||
|
|
||||||
var color = textureSampleLevel( stripeTex, linearSampler, uv, 0.0 ).rgb;
|
var color = textureSampleLevel( stripeTex, linearSampler, vec2<f32>(uv.x, 1.0 - uv.y), 0.0 ).rgb;
|
||||||
|
|
||||||
var brightness = getBrightness(uv);
|
var brightness = getBrightness(uv);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user