diff --git a/demo/3dt.html b/demo/3dt.html
index c01e635..428ecb0 100644
--- a/demo/3dt.html
+++ b/demo/3dt.html
@@ -25,11 +25,12 @@
+
void main() {
vec2 uv = gl_FragCoord.xy / resolution.xy;
vec3 col = texture(tex_avatar, uv).rgb;
- col = texture(test3d, vec3(uv.xy, mouse.x)).rrr;
+ col *= texture(test3d, vec3(uv.xy, mouse.x)).rrr;
float dist = distance(uv, mouse.xy);
float circle = smoothstep(.025, .026, dist) * .5 + .5;
diff --git a/src/repa-shader.js b/src/repa-shader.js
index f0190d0..0aa6c47 100644
--- a/src/repa-shader.js
+++ b/src/repa-shader.js
@@ -263,8 +263,9 @@ class RepaShader extends HTMLElement {
_collectTextures() {
this._textures = [];
+ this._textures3d = [];
- this.querySelectorAll('repa-texture').forEach(t => {
+ this.querySelectorAll('repa-texture:not([t3d])').forEach(t => {
const texture = this._gl.createTexture();
this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
@@ -282,54 +283,22 @@ class RepaShader extends HTMLElement {
});
});
- // TODO 3d texture experiment
- let texture = this._gl.createTexture();
- this._gl.bindTexture(this._gl.TEXTURE_3D, texture);
- this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MIN_FILTER, this._gl.NEAREST);
- this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MAG_FILTER, this._gl.NEAREST);
- this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_S, this._gl.CLAMP_TO_EDGE);
- this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_T, this._gl.CLAMP_TO_EDGE);
- this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_R, this._gl.CLAMP_TO_EDGE);
- // ???
- this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_BASE_LEVEL, 0);
- this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MAX_LEVEL, 0);
+ this.querySelectorAll('repa-texture[t3d]').forEach(t => {
+ let texture = this._gl.createTexture();
+ this._gl.bindTexture(this._gl.TEXTURE_3D, texture);
+ this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MIN_FILTER, this._getFilter(t.minFilter));
+ this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MAG_FILTER, this._getFilter(t.magFilter));
+ this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_S, this._getWrap(t.wrapS));
+ this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_T, this._getWrap(t.wrapT));
+ this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_R, this._getWrap(t.wrapR));
- let size = 32;
- let t3data = new Uint8Array(size * size * size);
+ this._gl.texImage3D(this._gl.TEXTURE_3D, 0, this._gl.RGBA, 1, 1, 1, 0, this._gl.RGBA, this._gl.UNSIGNED_BYTE, new Uint8Array([64, 255, 128, 255]));
- for (let i = 0; i < size; i++) {
- for (let j = 0; j < size; j++) {
- for (let k = 0; k < size; k++) {
- let index = i * size * size + j * size + k;
- t3data[index] = (i * j * k) % 255;
- }
- }
- }
-
- this._gl.texImage3D(
- this._gl.TEXTURE_3D, // target
- 0, // level
- this._gl.R8, // format - red8 (1byte)
- size, // width
- size, // height
- size, // depth
- 0, // border
- this._gl.RED, // format - red
- this._gl.UNSIGNED_BYTE, // type - unsigned byte
- t3data // data
- );
-
- this._textures3d = [];
- this._textures3d.push({
- texture,
- texElement: {
- name: 'test3d',
- width: size,
- height: size,
- depth: size,
- },
+ this._textures3d.push({
+ texture,
+ texElement: t
+ });
});
- // TODO end of 3d texture experiment
}
async reset(time) {
@@ -375,8 +344,6 @@ class RepaShader extends HTMLElement {
return;
}
- // TODO sound?
-
if (this._program) {
this._gl.deleteProgram(this._program);
}
@@ -401,11 +368,10 @@ class RepaShader extends HTMLElement {
t.texElement.forceUpdate();
});
- // TODO 3d texture experiment
this._textures3d.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
- // TODO
+ t.texElement.forceUpdate();
});
this._attLocation = this._gl.getAttribLocation(this.program, 'position');
@@ -465,13 +431,17 @@ class RepaShader extends HTMLElement {
this._gl.uniform2fv(this._uniLocation[t.texElement.name+'_d'], [t.texElement.width || 1, t.texElement.height || 1]);
});
- // TODO 3d texture experiment
this._textures3d.forEach((t, i) => {
this._gl.activeTexture(this._gl.TEXTURE0 + i + this.mrt + this._textures.length);
this._gl.bindTexture(this._gl.TEXTURE_3D, t.texture);
- this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, 0);
- // TODO update, etc
+ // update if needed
+ if (t.texElement.shouldUpdate) {
+ const format = this._getFormat(t.texElement.format);
+ this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, 0);
+
+ this._gl.texImage3D(this._gl.TEXTURE_3D, 0, format, t.texElement.width, t.texElement.height, t.texElement.depth, 0, format, this._gl.UNSIGNED_BYTE, t.texElement.update());
+ }
this._gl.uniform1i(this._uniLocation[t.texElement.name], i + this.mrt + this._textures.length);
this._gl.uniform3fv(this._uniLocation[t.texElement.name+'_d'], [t.texElement.width || 1, t.texElement.height || 1, t.texElement.depth || 1]);
@@ -591,7 +561,6 @@ void main() {
}
get postFS() {
- // TODO 3d texture experiment
return `#version 300 es
precision mediump float;
uniform sampler2D drawTexture;
@@ -636,7 +605,6 @@ void main() {
uniform vec2 ${t.texElement.name}_d;
`;
}).join('') +
- // TODO 3d texture experiment
this._textures3d.map(t => {
return `
uniform sampler3D ${t.texElement.name};
diff --git a/src/repa-texture.js b/src/repa-texture.js
index dedc752..ea65665 100644
--- a/src/repa-texture.js
+++ b/src/repa-texture.js
@@ -33,7 +33,7 @@ class RepaTexture extends HTMLElement {
}
static get observedAttributes() {
- return ['src', 'type', 'mag-filter', 'min-filter', 'filter', 'wrap-s', 'wrap-t', 'wrap', 'format'];
+ return ['src', 'type', 'mag-filter', 'min-filter', 'filter', 'wrap-s', 'wrap-t', 'wrap-r', 'wrap', 'format'];
}
attributeChangedCallback(name, oldValue, newValue) {
@@ -86,8 +86,29 @@ class RepaTexture extends HTMLElement {
this._forceUpdate = true;
} else if (this.textContent) {
this.content = JSON.parse(this.textContent);
+ } else if (this.t3d) { // TODO 3d texture experiment
+ let size = 32;
+ this._width = size;
+ this._height = size;
+ this._depth = size;
+
+ let t3data = new Uint8Array(size * size * size);
+
+ for (let i = 0; i < size; i++) {
+ for (let j = 0; j < size; j++) {
+ for (let k = 0; k < size; k++) {
+ let index = i * size * size + j * size + k;
+ t3data[index] = (i * j * k) % 255;
+ }
+ }
+ }
+
+ this._content = t3data;
+ this._forceUpdate = true;
+ this._format = 'luminance';
+ this.ready = true;
} else {
- this.logger.error('Source cannot be loaded');
+ this.logger.error('Texture content cannot be loaded!');
}
}
@@ -212,8 +233,12 @@ class RepaTexture extends HTMLElement {
return null;
}
+ get t3d() {
+ return this.hasAttribute('t3d');
+ }
+
get flipY() {
- return this.type !== 'raw';
+ return !this.t3d && this.type !== 'raw';
}
setContent(data) {
@@ -334,6 +359,10 @@ class RepaTexture extends HTMLElement {
return this._height || this.ref?.videoHeight || this.ref?.height || 0;
}
+ get depth() {
+ return this._depth || this.ref?.depth || 0;
+ }
+
get magFilter() {
return this._filter || this.getAttribute('mag-filter') || this.getAttribute('filter') || 'linear';
}
@@ -350,6 +379,10 @@ class RepaTexture extends HTMLElement {
return this.getAttribute('wrap-t') || this.getAttribute('wrap') || 'clamp-to-edge';
}
+ get wrapR() {
+ return this.getAttribute('wrap-r') || this.getAttribute('wrap') || 'clamp-to-edge';
+ }
+
get format() {
return this._format || this.getAttribute('format') || 'rgba';
}