I have this really weird situation where I tried to read out pixels from a WebGL canvas, which didn't work. Then I wrote another version of the same program just without classes, and for some reason it works here. Maybe I did some very basic mistake, but I really cannot spot the (semantic) difference between those two.
In the following snippet, I (Firefox 88.0 on Linux 5.11.15-arch1-2) see the console printing 128 and 0, the 128 stemming from the code outside of the class, which seems correct, as the shader is drawing 0.5 for every pixel and channel, and the 0 stemming from the code inside the class.
[EDIT] I already saw this question, but they are talking about the read having to occur in the same event as the draw, which is, as far as I can tell, true for both of my cases (two consecutive lines). Also they are talking about an on-screen canvas, while I rendered to a framebuffer, not sure whether that makes a difference, but I assumed framebuffers to be more persistent.
class Gpgpu {
constructor(w, h, vs, fs, ans, uns) {
this.gl = document.createElement("canvas").getContext("webgl");
this.gl.canvas.width = w;
this.gl.canvas.height = h;
this.gl.viewport(0, 0, w, h);
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.gl.createFramebuffer());
this.out = new Uint8Array(w * h * 4);
}
spg(vs, fs, ans, uns) {
let p = this.gl.createProgram();
for (let ss of [
{ t: this.gl.VERTEX_SHADER, d: vs },
{ t: this.gl.FRAGMENT_SHADER, d: fs }
]) {
let s = this.gl.createShader(ss.t);
this.gl.shaderSource(s, ss.d);
this.gl.compileShader(s);
this.gl.attachShader(p, s);
}
this.gl.linkProgram(p);
this.gl.useProgram(p);
this.als = {};
for (let an of ans) {
this.als[an] = {
l: this.gl.getAttribLocation(p, an),
b: this.gl.createBuffer()
};
}
this.uls = {};
for (let un of uns) {
this.uls[un] = this.gl.getUniformLocation(p, un);
}
}
sad(n, ads) {
this.n = n;
for (let an in ads) {
let al = this.als[an];
let ad = ads[an];
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, al.b);
this.gl.bufferData(
this.gl.ARRAY_BUFFER,
Float32Array.from(ad),
this.gl.STATIC_DRAW
);
this.gl.enableVertexAttribArray(al.l);
this.gl.vertexAttribPointer(al.l, 2, this.gl.FLOAT, false, 0, 0);
}
}
drw() {
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.n);
}
}
class Cloth {
constructor(w, h) {
this.gpu = new Gpgpu(w, h);
this.tex = this.gpu.gl.createTexture();
this.gpu.spg(
document.getElementById("vs").innerHTML,
document.getElementById("fs").innerHTML,
["a_position"],
[]
);
this.gpu.sad(6, {
a_position: [-1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1]
});
this.gpu.gl.bindTexture(this.gpu.gl.TEXTURE_2D, this.tex);
this.gpu.gl.texImage2D(
this.gpu.gl.TEXTURE_2D,
0,
this.gpu.gl.RGBA,
w,
h,
0,
this.gpu.gl.RGBA,
this.gpu.gl.UNSIGNED_BYTE,
null
);
}
t() {
this.gpu.gl.framebufferTexture2D(
this.gpu.gl.FRAMEBUFFER,
this.gpu.gl.COLOR_ATTACHMENT0,
this.gpu.gl.TEXTURE_2D,
this.tex,
0
);
this.gpu.drw();
this.gpu.gl.readPixels(
0,
0,
this.w,
this.h,
this.gpu.gl.RGBA,
this.gpu.gl.UNSIGNED_BYTE,
this.gpu.out
);
console.log(this.gpu.out[0]);
}
}
const w = 10;
const h = 10;
const gpu = new Gpgpu(w, h);
const tex = gpu.gl.createTexture();
gpu.spg(
document.getElementById("vs").innerHTML,
document.getElementById("fs").innerHTML,
["a_position"],
[]
);
gpu.sad(6, {
a_position: [-1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1]
});
gpu.gl.bindTexture(gpu.gl.TEXTURE_2D, tex);
gpu.gl.texImage2D(
gpu.gl.TEXTURE_2D,
0,
gpu.gl.RGBA,
w,
h,
0,
gpu.gl.RGBA,
gpu.gl.UNSIGNED_BYTE,
null
);
gpu.gl.framebufferTexture2D(
gpu.gl.FRAMEBUFFER,
gpu.gl.COLOR_ATTACHMENT0,
gpu.gl.TEXTURE_2D,
tex,
0
);
gpu.drw();
gpu.gl.readPixels(0, 0, w, h, gpu.gl.RGBA, gpu.gl.UNSIGNED_BYTE, gpu.out);
console.log(gpu.out[0]);
new Cloth(10, 10).t();
<script type="x-shader/x-vertex" id="vs">
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
</script>
<script type="x-shader/x-fragment" id="fs">precision highp float;
void main() {
gl_FragColor = vec4(0.5, 0.5, 0.5, 0.5);
}
</script>from Reading From WebGL Canvas Seems To Work Inconsistently
No comments:
Post a Comment