Skip to content

Commit b2a71c1

Browse files
committed
feat: refactor shaders to support @content with canvas element
1 parent d381945 commit b2a71c1

File tree

3 files changed

+48
-32
lines changed

3 files changed

+48
-32
lines changed

src/component.js

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -469,18 +469,32 @@ if (typeof HTMLElement !== 'undefined') {
469469
const set_shader_prop = v => {
470470
element.style.setProperty('background', 'url("' + v + '") no-repeat 50%/cover');
471471
}
472-
473472
const tick = ([v, animated]) => {
474-
if (animated) {
475-
this.animations.push(create_animation(t => {
476-
set_shader_prop(v(t, width, height, images));
477-
}));
473+
if (target.type === 'content') {
474+
let canvas = v(0, width, height, images);
475+
element.replaceChildren(canvas);
476+
if (animated) {
477+
this.animations.push(create_animation(t => {
478+
v(t, width, height, images);
479+
}));
480+
} else {
481+
let render = this.shader_renders.get(target.selector);
482+
if (!this.shader_renders.has(target.selector)) {
483+
this.shader_renders.set(target.selector, v);
484+
}
485+
}
478486
} else {
479-
let render = this.shader_renders.get(target.selector);
480-
if (!this.shader_renders.has(target.selector)) {
481-
this.shader_renders.set(target.selector, v);
487+
if (animated) {
488+
this.animations.push(create_animation(t => {
489+
set_shader_prop(v(t, width, height, images).toDataURL());
490+
}));
491+
} else {
492+
let render = this.shader_renders.get(target.selector);
493+
if (!this.shader_renders.has(target.selector)) {
494+
this.shader_renders.set(target.selector, v);
495+
}
496+
set_shader_prop(v(0, width, height, images).toDataURL());
482497
}
483-
set_shader_prop(v(0, width, height, images));
484498
}
485499
}
486500

@@ -498,7 +512,7 @@ if (typeof HTMLElement !== 'undefined') {
498512
})).then(fn);
499513
}
500514

501-
if (!this.observers.has(target)) {
515+
if (!this.observers.has(target.selector)) {
502516
let observer = new ResizeObserver(() => {
503517
let rect = element.getBoundingClientRect();
504518
width = rect.width;
@@ -511,7 +525,7 @@ if (typeof HTMLElement !== 'undefined') {
511525
images = result;
512526
let render = this.shader_renders.get(target.selector);
513527
if (render) {
514-
set_shader_prop(render(0, width, height, images));
528+
set_shader_prop(render(0, width, height, images).toDataURL());
515529
}
516530
});
517531
});
@@ -640,11 +654,12 @@ if (typeof HTMLElement !== 'undefined') {
640654

641655
build_grid(compiled, grid) {
642656
const { has_transition, has_animation } = compiled.props;
643-
let has_delay = (has_transition || has_animation);
644657
const { uniforms, content, styles } = compiled;
658+
let has_delay = (has_transition || has_animation);
659+
let has_content = Object.keys(content).length;
645660
this.doodle.innerHTML = `
646661
<style>${get_basic_styles(grid) + styles.main}</style>
647-
${(styles.cells || styles.container || Object.keys(content).length) ? create_grid(grid, compiled) : ''}
662+
${(styles.cells || styles.container || has_content) ? create_grid(grid, compiled) : ''}
648663
`;
649664
if (has_delay) {
650665
this.reflow();
@@ -654,7 +669,9 @@ if (typeof HTMLElement !== 'undefined') {
654669
get_basic_styles(grid) +
655670
styles.all
656671
));
657-
672+
if (has_content) {
673+
replace(Object.values(compiled.content).join(' '));
674+
}
658675
this.bind_uniforms(uniforms);
659676
}
660677

@@ -789,7 +806,7 @@ function get_basic_styles(grid) {
789806
svg {
790807
position: absolute;
791808
}
792-
grid, svg {
809+
grid, svg, canvas {
793810
width: 100%;
794811
height: 100%
795812
}
@@ -798,8 +815,11 @@ function get_basic_styles(grid) {
798815

799816
function create_cell(x, y, z, content, child = '') {
800817
let id = cell_id(x, y, z);
801-
let head = content['#' + id] ?? '';
802818
let tail = child ?? '';
819+
let head = content['#' + id] ?? '';
820+
if (head.startsWith('${shader')) {
821+
head = '';
822+
}
803823
return `<cell id="${id}" part="cell">${head}${tail}</cell>`;
804824
}
805825

src/generator/css.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,12 @@ class Rules {
237237
};
238238
if (selector && selector.property === '@content') {
239239
target.type = 'content';
240-
}
241-
if (selector && selector.property === '@grid') {
240+
} else if (selector && selector.property === '@grid') {
242241
target.selector = ':host';
243-
}
244-
if (is_special_selector(selector)) {
242+
} else if (is_special_selector(selector)) {
245243
target.selector = selector;
246244
}
247-
if (!selector) {
245+
if (target.selector === 'cell') {
248246
target.selector = cell_selector;
249247
}
250248
return target;

src/generator/shaders.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { cache } from '../cache.js';
21
import { hash } from '../utils/index.js';
32

43
const DEFAULT_VERTEX_SHADER = `#version 300 es
@@ -8,6 +7,8 @@ const DEFAULT_VERTEX_SHADER = `#version 300 es
87
}
98
`;
109

10+
const SCREEN_QUAD_VERTICES = [-1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1];
11+
1112
function create_shader(gl, type, source) {
1213
const shader = gl.createShader(type);
1314
gl.shaderSource(shader, source);
@@ -31,6 +32,8 @@ function create_program(gl, vss, fss) {
3132
gl.deleteProgram(prog);
3233
}
3334

35+
gl.detachShader(prog, vs);
36+
gl.detachShader(prog, fs);
3437
gl.deleteShader(vs);
3538
gl.deleteShader(fs);
3639

@@ -73,11 +76,6 @@ function load_texture(gl, image, i) {
7376
}
7477

7578
export default function draw_shader(shaders, seed) {
76-
const result = cache.get(shaders);
77-
if (result) {
78-
return Promise.resolve(result);
79-
}
80-
8179
const canvas = document.createElement('canvas');
8280
const ratio = devicePixelRatio || 1;
8381

@@ -124,8 +122,7 @@ export default function draw_shader(shaders, seed) {
124122
const positionAttributeLocation = gl.getAttribLocation(program, 'position');
125123
const positionBuffer = gl.createBuffer();
126124
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
127-
const vertices = [-1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1];
128-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
125+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(SCREEN_QUAD_VERTICES), gl.STATIC_DRAW);
129126
gl.enableVertexAttribArray(positionAttributeLocation);
130127
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
131128

@@ -156,7 +153,7 @@ export default function draw_shader(shaders, seed) {
156153
let frame_index = 0;
157154
let current_time = 0;
158155

159-
return Promise.resolve(cache.set(shaders, [(t, w, h, textures) => {
156+
const render = (t, w, h, textures) => {
160157
gl.clear(gl.COLOR_BUFFER_BIT);
161158
if (shaders.width !== w || shaders.height !== h) {
162159
textures.forEach((n, i) => {
@@ -178,6 +175,7 @@ export default function draw_shader(shaders, seed) {
178175
current_time = t;
179176
}
180177
gl.drawArrays(gl.TRIANGLES, 0, 6);
181-
return canvas.toDataURL();
182-
}, is_animated]));
178+
return canvas;
179+
}
180+
return Promise.resolve([render, is_animated]);
183181
}

0 commit comments

Comments
 (0)