Adding glyphFlip and glyphRotation parameters.

This commit is contained in:
Rezmason
2024-09-10 21:41:59 -07:00
parent f14651c2b2
commit cee10bb1de
7 changed files with 37 additions and 14 deletions

View File

@@ -101,6 +101,8 @@ const defaults = {
glyphEdgeCrop: 0.0, // The border around a glyph in a font texture that should be cropped out
glyphHeightToWidth: 1, // The aspect ratio of glyphs
glyphVerticalSpacing: 1, // The ratio of the vertical distance between glyphs to their height
glyphFlip: false, // Whether to horizontally reflect the glyphs
glyphRotation: 0, // An angle to rotate the glyphs. Currently limited to 90° increments
hasThunder: false, // An effect that adds dramatic lightning flashes
isPolar: false, // Whether the glyphs arc across the screen or sit in a standard grid
rippleTypeName: null, // The variety of the ripple effect
@@ -134,12 +136,12 @@ const versions = {
megacity: {
font: "megacity",
animationSpeed: 0.5,
width: 40,
numColumns: 40,
},
neomatrixology: {
font: "neomatrixology",
animationSpeed: 0.8,
width: 40,
numColumns: 40,
palette: [
{ color: hsl(0.15, 0.9, 0.0), at: 0.0 },
{ color: hsl(0.15, 0.9, 0.2), at: 0.2 },
@@ -443,7 +445,6 @@ const paramMapping = {
font: { key: "font", parser: (s) => s },
effect: { key: "effect", parser: (s) => s },
camera: { key: "useCamera", parser: isTrue },
width: { key: "numColumns", parser: (s) => nullNaN(parseInt(s)) },
numColumns: { key: "numColumns", parser: (s) => nullNaN(parseInt(s)) },
density: { key: "density", parser: (s) => nullNaN(range(parseFloat(s), 0)) },
resolution: { key: "resolution", parser: (s) => nullNaN(parseFloat(s)) },
@@ -501,6 +502,11 @@ const paramMapping = {
},
volumetric: { key: "volumetric", parser: isTrue },
glyphFlip: { key: "glyphFlip", parser: isTrue },
glyphRotation: {
key: "glyphRotation",
parser: (s) => nullNaN(range(parseFloat(s), 0, Infinity)),
},
loops: { key: "loops", parser: isTrue },
fps: { key: "fps", parser: (s) => nullNaN(range(parseFloat(s), 0, 60)) },
skipIntro: { key: "skipIntro", parser: isTrue },
@@ -516,16 +522,17 @@ paramMapping.backgroundRGB = paramMapping.backgroundColor;
paramMapping.cursorRGB = paramMapping.cursorColor;
paramMapping.glintRGB = paramMapping.glintColor;
paramMapping.width = paramMapping.numColumns;
paramMapping.dropLength = paramMapping.raindropLength;
paramMapping.angle = paramMapping.slant;
paramMapping.colors = paramMapping.stripeColors;
export default (urlParams) => {
const validParams = Object.fromEntries(
Array.from(Object.entries(urlParams))
Object.entries(urlParams)
.filter(([key]) => key in paramMapping)
.map(([key, value]) => [paramMapping[key].key, paramMapping[key].parser(value)])
.filter(([_, value]) => value != null)
.filter(([_, value]) => value != null),
);
if (validParams.effect != null) {

View File

@@ -31,6 +31,8 @@ const brVert = [1, 1];
const quadVertices = [tlVert, trVert, brVert, tlVert, brVert, blVert];
export default ({ regl, config, lkg }) => {
const { mat2, mat4, vec2, vec3 } = glMatrix;
// The volumetric mode multiplies the number of columns
// to reach the desired density, and then overlaps them
const volumetric = config.volumetric;
@@ -49,6 +51,9 @@ export default ({ regl, config, lkg }) => {
const slantScale = 1 / (Math.abs(Math.sin(2 * config.slant)) * (Math.sqrt(2) - 1) + 1);
const showDebugView = config.effect === "none";
const glyphTransform = mat2.fromScaling(mat2.create(), vec2.fromValues(config.glyphFlip ? -1 : 1, 1));
mat2.rotate(glyphTransform, glyphTransform, (config.glyphRotation * Math.PI) / 180);
const commonUniforms = {
...extractEntries(config, ["animationSpeed", "glyphHeightToWidth", "glyphSequenceLength", "glyphTextureGridSize"]),
numColumns,
@@ -160,6 +165,7 @@ export default ({ regl, config, lkg }) => {
"glyphEdgeCrop",
"isPolar",
]),
glyphTransform,
density,
numQuadColumns,
numQuadRows,
@@ -212,7 +218,6 @@ export default ({ regl, config, lkg }) => {
// Camera and transform math for the volumetric mode
const screenSize = [1, 1];
const { mat4, vec3 } = glMatrix;
const transform = mat4.create();
if (volumetric && config.isometric) {
mat4.rotateX(transform, transform, (Math.PI * 1) / 8);

View File

@@ -8,7 +8,7 @@ const rippleTypes = {
const numVerticesPerQuad = 2 * 3;
const makeConfigBuffer = (device, configUniforms, config, density, gridSize) => {
const makeConfigBuffer = (device, configUniforms, config, density, gridSize, glyphTransform) => {
const configData = {
...config,
gridSize,
@@ -18,6 +18,7 @@ const makeConfigBuffer = (device, configUniforms, config, density, gridSize) =>
slantScale: 1 / (Math.abs(Math.sin(2 * config.slant)) * (Math.sqrt(2) - 1) + 1),
slantVec: [Math.cos(config.slant), Math.sin(config.slant)],
msdfPxRange: 4,
glyphTransform,
};
// console.table(configData);
@@ -25,7 +26,7 @@ const makeConfigBuffer = (device, configUniforms, config, density, gridSize) =>
};
export default ({ config, device, timeBuffer }) => {
const { mat4, vec3 } = glMatrix;
const { mat2, mat4, vec2, vec3 } = glMatrix;
const assets = [
loadTexture(device, config.glyphMSDFURL),
@@ -45,6 +46,9 @@ export default ({ config, device, timeBuffer }) => {
// rather than a single quad for our geometry
const numQuads = config.volumetric ? numCells : 1;
const glyphTransform = mat2.fromScaling(mat2.create(), vec2.fromValues(config.glyphFlip ? -1 : 1, 1));
mat2.rotate(glyphTransform, glyphTransform, (config.glyphRotation * Math.PI) / 180);
const transform = mat4.create();
if (config.volumetric && config.isometric) {
mat4.rotateX(transform, transform, (Math.PI * 1) / 8);
@@ -97,7 +101,7 @@ export default ({ config, device, timeBuffer }) => {
const [glyphMSDFTexture, glintMSDFTexture, baseTexture, glintTexture, rainShader] = await Promise.all(assets);
const rainShaderUniforms = structs.from(rainShader.code);
configBuffer = makeConfigBuffer(device, rainShaderUniforms.Config, config, density, gridSize);
configBuffer = makeConfigBuffer(device, rainShaderUniforms.Config, config, density, gridSize, glyphTransform);
const introCellsBuffer = device.createBuffer({
size: gridSize[0] * rainShaderUniforms.IntroCell.minSize,