From 2135bad80cbadb3eb3508478747634a0b1dea167 Mon Sep 17 00:00:00 2001 From: Gyuri Horak Date: Sun, 5 Mar 2023 13:35:01 +0100 Subject: [PATCH] raw texture data --- demo/index.html | 23 +++++++++++------------ src/repa-shader.js | 18 +++++++++++++++--- src/repa-texture.js | 42 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/demo/index.html b/demo/index.html index dcee0c7..ca2acff 100644 --- a/demo/index.html +++ b/demo/index.html @@ -26,20 +26,9 @@ + [[1, 2, 3, 4, 5, 6, 128, 255], [255, 128, 64, 32, 4, 3, 2, 1]] - +void main() { + vec2 uv = gl_FragCoord.xy / resolution.xy; + vec3 col = .5 + .5 * cos(uv.xyx + time + vec3(0, 2, 4)); + col *= texture(tex_avatar, uv).rgb; + + float dist = distance(uv, mouse.xy); + float circle = smoothstep(.1, .2, dist) * .5 + .5; + vec4 acolor = vec4(col * circle, circle); + outColor = vec4(acolor); +}
diff --git a/src/repa-shader.js b/src/repa-shader.js index d9fab59..07e6b83 100644 --- a/src/repa-shader.js +++ b/src/repa-shader.js @@ -244,11 +244,15 @@ class RepaShader extends HTMLElement { } _getWrap(wrap) { - return this._gl[wrap.toUpperCase().replaceAll('-', '_')] || this._gl.CLAMP_TO_EDGE; + return (wrap && this._gl[wrap.toUpperCase().replaceAll('-', '_')]) || this._gl.CLAMP_TO_EDGE; } _getFilter(filter) { - return this._gl[filter.toUpperCase().replaceAll('-', '_')] || this._gl.LINEAR; + return (filter && this._gl[filter.toUpperCase().replaceAll('-', '_')]) || this._gl.LINEAR; + } + + _getFormat(format) { + return (format && this._gl[format.toUpperCase().replaceAll('-', '_')]) || this._gl.RGBA; } _collectTextures() { @@ -382,7 +386,10 @@ class RepaShader extends HTMLElement { // update if needed if (t.texElement.shouldUpdate) { - this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA, this._gl.UNSIGNED_BYTE, t.texElement.update()); + const format = this._getFormat(t.texElement.format); + this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, t.texElement.flipY); + + this._gl.texImage2D(this._gl.TEXTURE_2D, 0, format, t.texElement.width, t.texElement.height, 0, format, this._gl.UNSIGNED_BYTE, t.texElement.update()); } this._gl.uniform1i(this._uniLocation[t.texElement.name], i + this.mrt); @@ -644,6 +651,11 @@ void main() { } } + // text content + if (!source) { + source = Array.from(this.childNodes).filter(n => n.nodeType === Node.TEXT_NODE).map(n => n.textContent).join('').trim(); + } + // fallback demo if (!source) { source = DEMO_FS; diff --git a/src/repa-texture.js b/src/repa-texture.js index 32cecaa..e347b33 100644 --- a/src/repa-texture.js +++ b/src/repa-texture.js @@ -16,10 +16,9 @@ const isVideo = (src) => { }; /* TODO - * - display content on canvas * - ready promise ** - * types: image, [video, webcam], [canvas, shader] + * types: image, [video, webcam], [canvas, shader], raw */ class RepaTexture extends HTMLElement { constructor() { @@ -34,7 +33,7 @@ class RepaTexture extends HTMLElement { } static get observedAttributes() { - return ['src', 'type', 'mag-filter', 'min-filter', 'filter', 'wrap-s', 'wrap-t', 'wrap']; + return ['src', 'type', 'mag-filter', 'min-filter', 'filter', 'wrap-s', 'wrap-t', 'wrap', 'format']; } attributeChangedCallback(name, oldValue, newValue) { @@ -85,6 +84,8 @@ class RepaTexture extends HTMLElement { if (this.ref) { this.ready = true; this._forceUpdate = true; + } else if (this.textContent) { + this.content = JSON.parse(this.textContent); } else { this.logger.error('Source cannot be loaded'); } @@ -199,21 +200,42 @@ class RepaTexture extends HTMLElement { } else if (this.ref.nodeName === 'REPA-SHADER') { return 'shader'; } + } else if (this._content) { + return 'raw'; } return null; } + get flipY() { + return this.type !== 'raw'; + } + + // Array of Arrays + set content(data) { + this.ready = true; + this._type = 'raw'; + this._format = 'luminance'; + this._forceUpdate = true; + + this._width = data[0].length; + this._height = data.length; + this._content = new Uint8Array(this._width * this._height); + + data.forEach((row, y) => { + this._content.set(row, y * this._width); + }); + } + get content() { if (this.ref) { if (this.type === 'shader') { return this.ref.target; - } else { - return this.ref; } + return this.ref; } - return null; + return this._content; } _guessType(src) { @@ -253,11 +275,11 @@ class RepaTexture extends HTMLElement { } get width() { - return this.ref?.videoWidth || this.ref?.width || 0; + return this._width || this.ref?.videoWidth || this.ref?.width || 0; } get height() { - return this.ref?.videoHeight || this.ref?.height || 0; + return this._height || this.ref?.videoHeight || this.ref?.height || 0; } get magFilter() { @@ -276,6 +298,10 @@ class RepaTexture extends HTMLElement { return this.getAttribute('wrap-t') || this.getAttribute('wrap') || 'clamp-to-edge'; } + get format() { + return this._format || this.getAttribute('format') || 'rgba'; + } + get name() { if (!this._name) { let name = this.getAttribute('name');