texture updating

This commit is contained in:
Gyuri Horák 2023-02-25 19:56:04 +01:00
parent 5c137b4d23
commit ae27c95b3d
Signed by: dyuri
GPG Key ID: 4993F07B3EAE8D38
3 changed files with 76 additions and 8 deletions

View File

@ -24,10 +24,22 @@
</head> </head>
<body> <body>
<repa-shader id="demoshader" fs-input="fsinput" alpha mouse snippets="noise.glsl" width=512 height=512> <repa-shader id="demoshader" fs-input="fsinput" alpha mouse snippets="noise.glsl" width=512 height=512>
<repa-texture src="avatar.png"></repa-texture> <repa-texture src="avatar.png" name="tex_avatar"></repa-texture>
<repa-texture src="futas.mp4"></repa-texture> <repa-texture src="futas.mp4"></repa-texture>
<!-- repa-texture src="webcam"></repa-texture --> <!-- repa-texture src="webcam"></repa-texture -->
<!-- repa-texture ref="demoshader"></repa-texture --> <!-- repa-texture ref="demoshader"></repa-texture -->
<script type="x-shader/x-fragment">
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, 1.-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);
}
</script>
<script type="x-shader/x-fragmen[DELETE]t"> <script type="x-shader/x-fragmen[DELETE]t">
// https://twigl.app/?ol=true&ss=-NOAlYulOVLklxMdxBDx // https://twigl.app/?ol=true&ss=-NOAlYulOVLklxMdxBDx
void main() { void main() {

View File

@ -243,9 +243,33 @@ class RepaShader extends HTMLElement {
this._resetBuffer(this.frontbuffer); this._resetBuffer(this.frontbuffer);
} }
_collectTextures() {
this._textures = [];
this.querySelectorAll('repa-texture').forEach(t => {
const texture = this._gl.createTexture();
this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
// TODO get params from attributes
this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.CLAMP_TO_EDGE);
this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_T, this._gl.CLAMP_TO_EDGE);
this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, this._gl.LINEAR);
this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, this._gl.LINEAR);
// fill texture with default black
this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, 1, 1, 0, this._gl.RGBA, this._gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
this._textures.push({
texture,
texElement: t,
});
});
}
async reset(time) { async reset(time) {
this._resizeTarget(); this._resizeTarget();
this._resetBuffers(); this._resetBuffers();
this._collectTextures();
this.frontbuffer = this._createBuffer(this._target.width, this._target.height); this.frontbuffer = this._createBuffer(this._target.width, this._target.height);
this.backbuffer = this._createBuffer(this._target.width, this._target.height); this.backbuffer = this._createBuffer(this._target.width, this._target.height);
@ -298,6 +322,12 @@ class RepaShader extends HTMLElement {
this._uniLocation[`backbuffer${i}`] = this._gl.getUniformLocation(this.program, `backbuffer${i}`); this._uniLocation[`backbuffer${i}`] = this._gl.getUniformLocation(this.program, `backbuffer${i}`);
} }
// textures
this._textures.forEach((t) => {
this._uniLocation[t.texElement.name] = this._gl.getUniformLocation(this.program, t.texElement.name); // texture
this._uniLocation[t.texElement.name+'_d'] = this._gl.getUniformLocation(this.program, t.texElement.name+'_d'); // dimensions
});
this._attLocation = this._gl.getAttribLocation(this.program, 'position'); this._attLocation = this._gl.getAttribLocation(this.program, 'position');
this._mousePosition= [0, 0, 0]; this._mousePosition= [0, 0, 0];
this._startTime = Date.now(); this._startTime = Date.now();
@ -336,6 +366,20 @@ class RepaShader extends HTMLElement {
this._gl.uniform1f(this._uniLocation.time, this._nowTime * .001); this._gl.uniform1f(this._uniLocation.time, this._nowTime * .001);
this._gl.uniform1f(this._uniLocation.frame, this._frame); this._gl.uniform1f(this._uniLocation.frame, this._frame);
// textures
this._textures.forEach((t, i) => {
this._gl.activeTexture(this._gl.TEXTURE0 + i + this.mrt);
this._gl.bindTexture(this._gl.TEXTURE_2D, t.texture);
// 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());
}
this._gl.uniform1i(this._uniLocation[t.texElement.name], i + this.mrt);
// TODO dimension
});
this._gl.drawArrays(this._gl.TRIANGLE_STRIP, 0, 4); this._gl.drawArrays(this._gl.TRIANGLE_STRIP, 0, 4);
// fill buffer // fill buffer
@ -487,6 +531,14 @@ void main() {
return targets.join(''); return targets.join('');
} }
_getTextures() {
return this._textures.map(t => {
return `
uniform sampler2D ${t.texElement.name};
`;
}).join('');
}
async getVS() { async getVS() {
let source = ''; let source = '';
@ -541,14 +593,14 @@ void main() {
break; break;
case 'geeker': case 'geeker':
snippets = await this._getSnippets(); snippets = await this._getSnippets();
start = CHUNKS.es300 + CHUNKS.geeker + this._getRenderTargets() + snippets; start = CHUNKS.es300 + CHUNKS.geeker + this._getRenderTargets() + this._getTextures() + snippets;
break; break;
case 'geekest': case 'geekest':
snippets = await this._getSnippets(); snippets = await this._getSnippets();
if (!snippets) { if (!snippets) {
snippets = await this.getSnippet('noise.glsl'); snippets = await this.getSnippet('noise.glsl');
} }
start = CHUNKS.es300 + CHUNKS.geeker + this._getRenderTargets() + snippets + CHUNKS.geekestStart; start = CHUNKS.es300 + CHUNKS.geeker + this._getRenderTargets() + this._getTextures() + snippets + CHUNKS.geekestStart;
end = CHUNKS.geekestEnd; end = CHUNKS.geekestEnd;
break; break;
} }

View File

@ -39,7 +39,7 @@ class RepaTexture extends HTMLElement {
} }
static get observedAttributes() { static get observedAttributes() {
return ['src', 'type', 'name', 'mag-filter', 'min-filter', 'wrap-s', 'wrap-t']; return ['src', 'type', 'mag-filter', 'min-filter', 'wrap-s', 'wrap-t'];
} }
attributeChangedCallback(name, oldValue, newValue) { attributeChangedCallback(name, oldValue, newValue) {
@ -124,11 +124,10 @@ class RepaTexture extends HTMLElement {
_hideInDOM(el) { _hideInDOM(el) {
const hiddenEl = document.createElement('div'); const hiddenEl = document.createElement('div');
hiddenEl.setAttribute('hidden', '');
hiddenEl.style.width = hiddenEl.style.height = '1px'; hiddenEl.style.width = hiddenEl.style.height = '1px';
hiddenEl.style.top = hiddenEl.style.left = '1px';
hiddenEl.style.overflow = 'hidden'; hiddenEl.style.overflow = 'hidden';
hiddenEl.style.position = 'absolute'; hiddenEl.style.position = 'fixed';
hiddenEl.style.top = hiddenEl.style.left = '-100px';
hiddenEl.style.zIndex = '-100'; hiddenEl.style.zIndex = '-100';
hiddenEl.style.opacity = '0'; hiddenEl.style.opacity = '0';
hiddenEl.style.pointerEvents = 'none'; hiddenEl.style.pointerEvents = 'none';
@ -238,8 +237,13 @@ class RepaTexture extends HTMLElement {
return null; return null;
} }
update() {
this._forceUpdate = false;
return this.content;
}
get shouldUpdate() { get shouldUpdate() {
return this._forceUpdate || (this.ref && this.ref instanceof HTMLVideoElement && this.ref.readyState === this.ref.HAVE_ENOUGH_DATA); return this.ready && (this._forceUpdate || (this.ref && this.ref instanceof HTMLVideoElement && this.ref.readyState === this.ref.HAVE_ENOUGH_DATA));
} }
get width() { get width() {