5

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 の時点で何もしていないのでしょうか?

4

1 に答える 1

2

問題のある行は次のとおりです。

var array = new Uint8ClampedArray(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, array);

GL_UNSIGNED_BYTE正しく型指定された配列を渡す必要があるように型を指定すると、 FF は失敗します。ここでの正しい型はUint8ArrayではなくUint8ClampedArrayです。

FF コンソール ログを確認すると、次のようなエラー メッセージが表示されます。これらのアレイ タイプを交換することで解決されます。

Error: WebGL: readPixels: Mismatched type/pixels types
于 2012-09-16T23:18:50.650 に答える