diff --git a/src/control.html b/src/control.html index 1adf037..8120fbc 100644 --- a/src/control.html +++ b/src/control.html @@ -139,6 +139,7 @@ + diff --git a/src/control.js b/src/control.js index 0bbefeb..4dd7f17 100644 --- a/src/control.js +++ b/src/control.js @@ -157,7 +157,17 @@ function glbLabel(name) { : 'Il modello ruota a tempo di musica nella famiglia “Modello 3D”.'; } if (glbPath) glbLabel(glbPath.split('/').pop()); +// every shader family can be a backdrop too (fluid/interactive/3D excluded: +// fluids are the explicit options above, the others can't render as layers) +EFFECTS.families.forEach((name, fi) => { + if (/^Interattivo|^Modello 3D|^Fluido/.test(name)) return; + const o = document.createElement('option'); + o.value = 'fam:' + fi; + o.textContent = name; + $('#glb-bg').appendChild(o); +}); $('#glb-bg').value = glbBg; +if (!$('#glb-bg').value) { glbBg = 'gradient'; $('#glb-bg').value = 'gradient'; } $('#glb-bg').addEventListener('change', (e) => { glbBg = e.target.value; localStorage.setItem('glbbg', glbBg); diff --git a/src/visualizer.js b/src/visualizer.js index 684a0f8..807f53c 100644 --- a/src/visualizer.js +++ b/src/visualizer.js @@ -114,9 +114,21 @@ class Visualizer { if (e.isModel3d && window.ModelSim) { if (!this.model3d) this.model3d = new window.ModelSim(gl); if (this._pendingGlb) { this.model3d.setModel(this._pendingGlb); this._pendingGlb = null; } - // optional fluid backdrop behind the model (modelBg: ink/fire/ring/...) + // optional backdrop behind the model: a fluid mode ('ink'/'fire'/...) + // or any shader family ('fam:'), tinted with the active palette const bg = this.modelBg || 'gradient'; - if (bg !== 'gradient' && window.FluidSim) { + if (bg.indexOf('fam:') === 0 && window.EFFECTS) { + const fi = parseInt(bg.slice(4), 10); + const base = window.EFFECTS.list.find(x => x.family === fi && !x.isFluid && !x.isInteractive && !x.isModel3d); + if (base) { + const bgEff = Object.assign({}, base, { colorA: e.colorA, colorB: e.colorB, + hueBase: e.hueBase, hueCycle: e.hueCycle, sat: e.sat, audioMix: e.audioMix }); + this._renderUber(timeSec, audio, bgEff); + this.model3d.render(timeSec, audio, e, this.canvas, null, true); + return; + } + } + if (bg !== 'gradient' && bg.indexOf('fam:') !== 0 && window.FluidSim) { if (!this.fluid) this.fluid = new window.FluidSim(gl); this.fluid.render(timeSec, audio, Object.assign({}, e, { fluidMode: bg }), this.canvas); this.model3d.render(timeSec, audio, e, this.canvas, null, true); @@ -142,6 +154,12 @@ class Visualizer { this.fluid.render(timeSec, audio, e, this.canvas); return; } + this._renderUber(timeSec, audio, e); + } + + // The parametric uber-shader pass (also used as a backdrop for the model). + _renderUber(timeSec, audio, e) { + const gl = this.gl, u = this.u; gl.useProgram(this.program); gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo); gl.enableVertexAttribArray(this.aPos);