WebGL を使用して画像処理 (Brad Larson のGPUImageまたはチュートリアルWebGL Fundamentalsと同様) を実行した後、ピクセルを消費する CPU ステップを実行しています。残念ながら、 を呼び出すとgl.readPixels
、Firefox でバッファがすべて黒くなります。なんで?
スタンドアロンの例を次に示します: http://jsfiddle.net/yonran/8C3n5/ Chrome では、結果は「フレーム バッファ内に 924 の黒ピクセルと 100 の青のピクセルがあります」であるのに対し、Firefox では、結果は「フレーム バッファ内」です。フレームバッファには、1024 個の黒ピクセルと 0 個の青ピクセルがあります。」</p>
これは私がフレームバッファをセットアップする方法です:
function createTextureAndFramebuffer(gl, width, height) {
var outputTexture = createAndSetupTexture(gl);
// Make the texture the same size as the image.
gl.bindTexture(gl.TEXTURE_2D, outputTexture);
gl.texImage2D(
gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.bindTexture(gl.TEXTURE_2D, null);
// create a framebuffer
var fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
// attach a texture to it.
gl.framebufferTexture2D(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
return {texture: outputTexture, framebuffer: fbo};
}
function createAndSetupTexture(gl) {
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set up texture so we can render any size image and so we are
// working with pixels.
// This is necessary for non-power-of-two textures
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
return texture;
}
これは私がフレームバッファに描画する方法です:
ImageFilter.prototype = {
...,
draw: function() {
var gl = this.gl;
// Use the texture
gl.bindTexture(gl.TEXTURE_2D, this.texture);
// make this the framebuffer we are rendering to.
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Tell webgl the viewport setting needed for framebuffer.
gl.viewport(0, 0, this.outputWidth, this.outputHeight);
gl.useProgram(this.program);
this.applyUniforms();
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.flush();
},
vertexShaderString:
"attribute vec4 position;\n" +
"attribute vec4 inputTextureCoordinate;\n" +
"\n" +
"varying vec2 textureCoordinate;\n" +
"\n" +
"void main()\n" +
"{\n" +
" gl_Position = position;\n" +
" textureCoordinate = inputTextureCoordinate.xy;\n" +
"}\n",
fragmentShaderString:
"varying highp vec2 textureCoordinate;\n" +
"\n" +
"uniform sampler2D inputImageTexture;\n" +
"\n" +
"void main()\n" +
"{\n" +
" gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n" +
"}\n"
};
そして、次のようにフレームバッファから読み取ります。
gl.bindFramebuffer(gl.FRAMEBUFFER, imageFilter.framebuffer);
var width = imageFilter.outputWidth, height = imageFilter.outputHeight;
var array = new Uint8ClampedArray(width * height * 4);
gl.finish();
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, array);
var blackPixels = 0, bluePixels = 0;
var firstBlueX, firstBlueY;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var idx = 4*(x + y*width);
var r = array[idx], g = array[idx+1], b = array[idx+2], a = array[idx+3];
if (r === 0 && g === 0 && b === 0)
blackPixels++;
else if (b === 255) {
bluePixels++;
if (firstBlueX == null) {
firstBlueX = x;
firstBlueY = y;
}
}
}
}
var el = document.createElement("div");
document.body.appendChild(el);
el.textContent = "The first canvas is drawn to a framebuffer and then drawn again on the second canvas. " +
"Within the framebuffer, there are " + blackPixels + " black pixels and " +
bluePixels + " blue pixels The first blue pixel is at (" + firstBlueX+ "," + firstBlueY + ") " +
"(origin is at bottom left).";
これは同期の問題かもしれないと思いましたが、読み取りgl.finish()
の前にまたはを追加setTimeout
しても役に立ちません。検索すると、マルチサンプリングによってフレームバッファが 0 になる可能性があることがわかりましたがantialias: false
、呼び出し内での設定canvas.getContext
は役に立ちません。
編集: 前readPixels
にピクセルを設定しようとしましたが、Firefox はピクセルの設定を解除しません。おそらくreadPixels
、まだ実装されておらず、14.0.1 の時点で何もしていないのでしょうか?