website update
This commit is contained in:
parent
e69f60b59f
commit
8e6e4380f4
|
|
@ -97,6 +97,7 @@ uniform int materialType;
|
||||||
uniform float brushRadius;
|
uniform float brushRadius;
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
uniform sampler2D u_collisionTex;
|
uniform sampler2D u_collisionTex;
|
||||||
|
uniform float initialSand;
|
||||||
|
|
||||||
in vec2 outUv;
|
in vec2 outUv;
|
||||||
|
|
||||||
|
|
@ -196,7 +197,7 @@ void main() {
|
||||||
if (frame == 0) {
|
if (frame == 0) {
|
||||||
float r = hash12(gl_FragCoord.xy);
|
float r = hash12(gl_FragCoord.xy);
|
||||||
float id = AIR;
|
float id = AIR;
|
||||||
if (r < 0.15)
|
if (r < initialSand)
|
||||||
{
|
{
|
||||||
id = SAND;
|
id = SAND;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,12 @@ export class FolkSand extends FolkBaseSet {
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static properties = {
|
||||||
|
initialSand: { type: Number, attribute: 'initial-sand' },
|
||||||
|
};
|
||||||
|
|
||||||
|
initialSand = 0.15;
|
||||||
|
|
||||||
#canvas = document.createElement('canvas');
|
#canvas = document.createElement('canvas');
|
||||||
#gl!: WebGL2RenderingContext;
|
#gl!: WebGL2RenderingContext;
|
||||||
|
|
||||||
|
|
@ -152,7 +158,17 @@ export class FolkSand extends FolkBaseSet {
|
||||||
// Create collision texture
|
// Create collision texture
|
||||||
this.#collisionTex = gl.createTexture()!;
|
this.#collisionTex = gl.createTexture()!;
|
||||||
gl.bindTexture(gl.TEXTURE_2D, this.#collisionTex);
|
gl.bindTexture(gl.TEXTURE_2D, this.#collisionTex);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, this.#bufferWidth, this.#bufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
gl.texImage2D(
|
||||||
|
gl.TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
gl.RGBA8,
|
||||||
|
this.#bufferWidth,
|
||||||
|
this.#bufferHeight,
|
||||||
|
0,
|
||||||
|
gl.RGBA,
|
||||||
|
gl.UNSIGNED_BYTE,
|
||||||
|
null,
|
||||||
|
);
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
|
@ -425,6 +441,9 @@ export class FolkSand extends FolkBaseSet {
|
||||||
gl.bindTexture(gl.TEXTURE_2D, this.#collisionTex);
|
gl.bindTexture(gl.TEXTURE_2D, this.#collisionTex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initialSandLoc = gl.getUniformLocation(this.#program, 'initialSand');
|
||||||
|
gl.uniform1f(initialSandLoc, this.initialSand);
|
||||||
|
|
||||||
let mx = (this.#pointer.x / gl.canvas.width) * this.#bufferWidth;
|
let mx = (this.#pointer.x / gl.canvas.width) * this.#bufferWidth;
|
||||||
let my = (1.0 - this.#pointer.y / gl.canvas.height) * this.#bufferHeight;
|
let my = (1.0 - this.#pointer.y / gl.canvas.height) * this.#bufferHeight;
|
||||||
let mpx = (this.#pointer.prevX / gl.canvas.width) * this.#bufferWidth;
|
let mpx = (this.#pointer.prevX / gl.canvas.width) * this.#bufferWidth;
|
||||||
|
|
@ -543,7 +562,17 @@ export class FolkSand extends FolkBaseSet {
|
||||||
|
|
||||||
// Update collision texture size
|
// Update collision texture size
|
||||||
gl.bindTexture(gl.TEXTURE_2D, this.#collisionTex);
|
gl.bindTexture(gl.TEXTURE_2D, this.#collisionTex);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, this.#bufferWidth, this.#bufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
gl.texImage2D(
|
||||||
|
gl.TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
gl.RGBA8,
|
||||||
|
this.#bufferWidth,
|
||||||
|
this.#bufferHeight,
|
||||||
|
0,
|
||||||
|
gl.RGBA,
|
||||||
|
gl.UNSIGNED_BYTE,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
// Re-render collision data after resize
|
// Re-render collision data after resize
|
||||||
this.#handleShapeTransform();
|
this.#handleShapeTransform();
|
||||||
|
|
@ -587,13 +616,7 @@ export class FolkSand extends FolkBaseSet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#createProgramFromStrings({
|
#createProgramFromStrings({ vertex, fragment }: { vertex: string; fragment: string }): WebGLProgram | undefined {
|
||||||
vertex,
|
|
||||||
fragment,
|
|
||||||
}: {
|
|
||||||
vertex: string;
|
|
||||||
fragment: string;
|
|
||||||
}): WebGLProgram | undefined {
|
|
||||||
const vertexShader = WebGLUtils.createShader(this.#gl, this.#gl.VERTEX_SHADER, vertex);
|
const vertexShader = WebGLUtils.createShader(this.#gl, this.#gl.VERTEX_SHADER, vertex);
|
||||||
const fragmentShader = WebGLUtils.createShader(this.#gl, this.#gl.FRAGMENT_SHADER, fragment);
|
const fragmentShader = WebGLUtils.createShader(this.#gl, this.#gl.FRAGMENT_SHADER, fragment);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,27 @@ import mkcert from 'vite-plugin-mkcert';
|
||||||
const canvasWebsiteDir = resolve(__dirname, './website/canvas');
|
const canvasWebsiteDir = resolve(__dirname, './website/canvas');
|
||||||
|
|
||||||
function getCanvasFiles() {
|
function getCanvasFiles() {
|
||||||
return readdirSync(canvasWebsiteDir).filter((file) => file.endsWith('.html'));
|
const files: { path: string; name: string }[] = [];
|
||||||
|
|
||||||
|
// Helper function to read directory recursively
|
||||||
|
const readDir = (dir: string, base = '') => {
|
||||||
|
readdirSync(dir, { withFileTypes: true }).forEach((dirent) => {
|
||||||
|
// Skip directories that start with underscore
|
||||||
|
if (dirent.name.startsWith('_')) return;
|
||||||
|
|
||||||
|
if (dirent.isDirectory()) {
|
||||||
|
readDir(resolve(dir, dirent.name), `${base}${dirent.name}/`);
|
||||||
|
} else if (dirent.name.endsWith('.html')) {
|
||||||
|
files.push({
|
||||||
|
path: `${base}${dirent.name}`,
|
||||||
|
name: dirent.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
readDir(canvasWebsiteDir);
|
||||||
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
const linkGenerator = (): Plugin => {
|
const linkGenerator = (): Plugin => {
|
||||||
|
|
@ -15,46 +35,41 @@ const linkGenerator = (): Plugin => {
|
||||||
transformIndexHtml(html: string, ctx: IndexHtmlTransformContext) {
|
transformIndexHtml(html: string, ctx: IndexHtmlTransformContext) {
|
||||||
if (!ctx.filename.endsWith('canvas/index.html')) return;
|
if (!ctx.filename.endsWith('canvas/index.html')) return;
|
||||||
const files = getCanvasFiles();
|
const files = getCanvasFiles();
|
||||||
// First, handle ungrouped files
|
|
||||||
const ungroupedFiles = files.filter(
|
|
||||||
(file) => !file.includes('index') && !file.startsWith('_') && !file.match(/^\[([^\]]+)\]/),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Then handle grouped files
|
// Handle ungrouped files (in root canvas directory)
|
||||||
|
const ungroupedFiles = files.filter((file) => !file.path.includes('/') && !file.name.includes('index'));
|
||||||
|
|
||||||
|
// Handle grouped files (in subdirectories)
|
||||||
const groups = files
|
const groups = files
|
||||||
.filter((file) => !file.includes('index') && file.match(/^\[([^\]]+)\]/))
|
.filter((file) => file.path.includes('/'))
|
||||||
.reduce(
|
.reduce(
|
||||||
(acc, file) => {
|
(acc, file) => {
|
||||||
const match = file.match(/^\[([^\]]+)\](.+)\.html$/);
|
const group = file.path.split('/')[0];
|
||||||
const group = match![1];
|
|
||||||
if (!acc[group]) acc[group] = [];
|
if (!acc[group]) acc[group] = [];
|
||||||
acc[group].push(file);
|
acc[group].push(file);
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{} as Record<string, string[]>,
|
{} as Record<string, typeof files>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Generate ungrouped HTML first
|
// Generate ungrouped HTML
|
||||||
const ungroupedHtml = ungroupedFiles
|
const ungroupedHtml = ungroupedFiles
|
||||||
.sort()
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
.map((file) => {
|
.map(({ path, name }) => {
|
||||||
const title = file.replace('.html', '').replaceAll('-', ' ');
|
const title = name.replace('.html', '').replaceAll('-', ' ');
|
||||||
return `<li><a href="${file}">${title}</a></li>`;
|
return `<li><a href="${path}">${title}</a></li>`;
|
||||||
})
|
})
|
||||||
.join('\n');
|
.join('\n');
|
||||||
|
|
||||||
// Then generate grouped HTML
|
// Generate grouped HTML
|
||||||
const groupedHtml = Object.entries(groups)
|
const groupedHtml = Object.entries(groups)
|
||||||
.sort(([a], [b]) => a.localeCompare(b))
|
.sort(([a], [b]) => a.localeCompare(b))
|
||||||
.map(([group, groupFiles]) => {
|
.map(([group, groupFiles]) => {
|
||||||
const groupHtml = groupFiles
|
const groupHtml = groupFiles
|
||||||
.sort()
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
.map((file) => {
|
.map(({ path, name }) => {
|
||||||
const title = file
|
const title = name.replace('.html', '').replaceAll('-', ' ');
|
||||||
.replace(/^\[[^\]]+\]/, '')
|
return `<li><a href="${path}">${title}</a></li>`;
|
||||||
.replace('.html', '')
|
|
||||||
.replaceAll('-', ' ');
|
|
||||||
return `<li><a href="${file}">${title}</a></li>`;
|
|
||||||
})
|
})
|
||||||
.join('\n');
|
.join('\n');
|
||||||
|
|
||||||
|
|
@ -84,7 +99,7 @@ export default defineConfig({
|
||||||
index: resolve(__dirname, './website/index.html'),
|
index: resolve(__dirname, './website/index.html'),
|
||||||
...getCanvasFiles().reduce(
|
...getCanvasFiles().reduce(
|
||||||
(acc, file) => {
|
(acc, file) => {
|
||||||
acc[`canvas/${file.replace('.html', '')}`] = resolve(canvasWebsiteDir, file);
|
acc[`canvas/${file.name.replace('.html', '')}`] = resolve(canvasWebsiteDir, file.name);
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{} as Record<string, string>,
|
{} as Record<string, string>,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&family=Pixelify+Sans&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..1000,0..1,0..1,0..1&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<title>Folk Canvas</title>
|
<title>Folk Canvas</title>
|
||||||
|
|
@ -16,27 +16,50 @@
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
folk-sand {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
font-family: 'Courier Prime', Courier, monospace;
|
position: relative;
|
||||||
|
font-family: 'Recursive', Courier, monospace;
|
||||||
|
font-variation-settings:
|
||||||
|
'slnt' 0,
|
||||||
|
'wght' 400,
|
||||||
|
'CASL' 1,
|
||||||
|
'CRSV' 0,
|
||||||
|
'MONO' 0;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 20px auto;
|
margin: 20px auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||||
background: #fff;
|
background: rgba(255, 255, 255, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
color: #2c3e50;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-variation-settings:
|
||||||
|
'CASL' 0,
|
||||||
|
'MONO' 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
color: #2c3e50;
|
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
|
font-weight: 800;
|
||||||
margin: 1em 0 0;
|
margin: 1em 0 0;
|
||||||
|
font-variation-settings: 'wght' 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
|
|
@ -46,14 +69,24 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 2em 1fr;
|
||||||
|
padding-left: 0;
|
||||||
|
text-indent: 0;
|
||||||
|
}
|
||||||
|
|
||||||
li::before {
|
li::before {
|
||||||
content: '>';
|
content: '➔';
|
||||||
color: #666;
|
justify-self: center;
|
||||||
margin-right: 1em;
|
}
|
||||||
|
|
||||||
|
#questions li::before {
|
||||||
|
content: attr(data-symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #34495e;
|
color: #22282f;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,12 +96,8 @@
|
||||||
|
|
||||||
#questions {
|
#questions {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
font-style: italic;
|
font-variation-settings: 'slnt' 1;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
li::before {
|
|
||||||
content: '-';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#disclaimer {
|
#disclaimer {
|
||||||
|
|
@ -76,13 +105,134 @@
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<script type="module">
|
||||||
|
import '@labs/standalone/folk-sand.ts';
|
||||||
|
|
||||||
|
const alchemicalSymbols = [
|
||||||
|
'🜁',
|
||||||
|
'🜂',
|
||||||
|
'🜃',
|
||||||
|
'🜄',
|
||||||
|
'🜅',
|
||||||
|
'🜆',
|
||||||
|
'🜇',
|
||||||
|
'🜈',
|
||||||
|
'🜉',
|
||||||
|
'🜊',
|
||||||
|
'🜋',
|
||||||
|
'🜌',
|
||||||
|
'🜍',
|
||||||
|
'🜎',
|
||||||
|
'🜏',
|
||||||
|
'🜐',
|
||||||
|
'🜑',
|
||||||
|
'🜒',
|
||||||
|
'🜓',
|
||||||
|
'🜔',
|
||||||
|
'🜕',
|
||||||
|
'🜖',
|
||||||
|
'🜗',
|
||||||
|
'🜘',
|
||||||
|
'🜙',
|
||||||
|
'🜚',
|
||||||
|
'🜛',
|
||||||
|
'🜜',
|
||||||
|
'🜝',
|
||||||
|
'🜞',
|
||||||
|
'🜟',
|
||||||
|
'🜠',
|
||||||
|
'🜡',
|
||||||
|
'🜢',
|
||||||
|
'🜣',
|
||||||
|
'🜤',
|
||||||
|
'🜥',
|
||||||
|
'🜦',
|
||||||
|
'🜧',
|
||||||
|
'🜨',
|
||||||
|
'🜩',
|
||||||
|
'🜪',
|
||||||
|
'🜫',
|
||||||
|
'🜬',
|
||||||
|
'🜭',
|
||||||
|
'🜮',
|
||||||
|
'🜯',
|
||||||
|
'🜰',
|
||||||
|
'🜱',
|
||||||
|
'🜲',
|
||||||
|
'🜳',
|
||||||
|
'🜴',
|
||||||
|
'🜵',
|
||||||
|
'🜶',
|
||||||
|
'🜸',
|
||||||
|
'🜹',
|
||||||
|
'🜺',
|
||||||
|
'🜻',
|
||||||
|
'🜼',
|
||||||
|
'🜾',
|
||||||
|
'🜿',
|
||||||
|
'🝀',
|
||||||
|
'🝁',
|
||||||
|
'🝂',
|
||||||
|
'🝃',
|
||||||
|
'🝄',
|
||||||
|
'🝅',
|
||||||
|
'🝆',
|
||||||
|
'🝈',
|
||||||
|
'🝉',
|
||||||
|
'🝊',
|
||||||
|
'🝋',
|
||||||
|
'🝌',
|
||||||
|
'🝍',
|
||||||
|
'🝎',
|
||||||
|
'🝏',
|
||||||
|
'🝐',
|
||||||
|
'🝑',
|
||||||
|
'🝒',
|
||||||
|
'🝓',
|
||||||
|
'🝔',
|
||||||
|
'🝕',
|
||||||
|
'🝖',
|
||||||
|
'🝗',
|
||||||
|
'🝘',
|
||||||
|
'🝙',
|
||||||
|
'🝚',
|
||||||
|
'🝛',
|
||||||
|
'🝜',
|
||||||
|
'🝝',
|
||||||
|
'🝞',
|
||||||
|
'🝟',
|
||||||
|
'🝠',
|
||||||
|
'🝡',
|
||||||
|
'🝢',
|
||||||
|
'🝣',
|
||||||
|
'🝤',
|
||||||
|
'🝥',
|
||||||
|
'🝦',
|
||||||
|
'🝧',
|
||||||
|
'🝩',
|
||||||
|
'🝪',
|
||||||
|
'🝬',
|
||||||
|
'🝭',
|
||||||
|
'🝮',
|
||||||
|
'🝯',
|
||||||
|
'🝰',
|
||||||
|
'🝲',
|
||||||
|
'🝳',
|
||||||
|
];
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const questionItems = document.querySelectorAll('#questions li');
|
||||||
|
questionItems.forEach((li) => {
|
||||||
|
const randomSymbol = alchemicalSymbols[Math.floor(Math.random() * alchemicalSymbols.length)];
|
||||||
|
li.setAttribute('data-symbol', randomSymbol);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<folk-sand initial-sand="0"></folk-sand>
|
||||||
<main>
|
<main>
|
||||||
<h1>
|
<h1> Folk Canvas [<a href="https://github.com/folk-canvas/folk-canvas">Github</a>] </h1>
|
||||||
Folk Canvas
|
|
||||||
<a href="https://github.com/folk-canvas/folk-canvas">(Github)</a>
|
|
||||||
</h1>
|
|
||||||
<ul id="questions">
|
<ul id="questions">
|
||||||
<li>How do we make the web feel more alive and less rigid and closed off?</li>
|
<li>How do we make the web feel more alive and less rigid and closed off?</li>
|
||||||
<li>How can we more easily compose web pages and their data together?</li>
|
<li>How can we more easily compose web pages and their data together?</li>
|
||||||
|
|
@ -99,8 +249,11 @@
|
||||||
>
|
>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Demos</h2>
|
<h2>Experiments from the lab</h2>
|
||||||
<p id="disclaimer">(Make sure to checkout the dev tools, all of the you see are just authored in HTML!)</p>
|
<p id="disclaimer">
|
||||||
|
These experiments (like this page) are very raw, intended to poke at new primitives and ideas. Make sure to
|
||||||
|
checkout the dev tools, all of the you see are just authored in HTML!
|
||||||
|
</p>
|
||||||
|
|
||||||
<ul id="links">
|
<ul id="links">
|
||||||
{{ LINKS }}
|
{{ LINKS }}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue