2017-06-12 39 views
0

我目前正在致電readPixels的演示。WebGL 2何時清除繪圖緩衝區?

This answer on SO是我可以在preserveDrawingBuffer選項上找到的大部分信息。

在測試過程中我觀察到在WebGL 2中this answer保持不變 - 您必須將preserveDrawingBuffer設置爲true

這是真的嗎?

是否有一個等效於preserveDrawingBuffer的OpenGL?

有什麼辦法可以將preserveDrawingBuffer設置爲false而仍然調用readPixels?

This answer使它看起來像你可以改爲gl.flush

preserveDrawingBuffer與刷新上下文是一樣的嗎?

回答

1

您不需要preserveDrawingBuffer: true即可致電readPixels。您需要在退出當前事件前致電readPixels

該規範說,如果您調用任何影響畫布的函數(gl.clear,gl.drawXXX),則瀏覽器將在下一次複合操作後清除畫布。當這種複合操作發生在瀏覽器上時。它可能在處理好幾個鼠標事件或鍵盤事件或點擊事件之後。訂單未定義。什麼是確定的是,直到目前的情況下出口,使

render 
read 

const gl = document.querySelector("canvas").getContext("webgl2"); 
 

 
render(); 
 
read(); // read in same event 
 

 
function render() { 
 
    gl.clearColor(.25, .5, .75, 1); 
 
    gl.clear(gl.COLOR_BUFFER_BIT); 
 
} 
 

 
function read() { 
 
    const pixel = new Uint8Array(4); 
 
    gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); 
 
    log(pixel); 
 
} 
 

 
function log(...args) { 
 
    const elem = document.createElement("pre"); 
 
    elem.textContent = [...args].join(' '); 
 
    document.body.appendChild(elem); 
 
}
<canvas></canvas>

作品,其中爲

render 
setTimeout(read, 1000); // some other event 

不工作就不會做到這一點

const gl = document.querySelector("canvas").getContext("webgl2"); 
 

 
render(); 
 
setTimeout(read, 1000); // read in other event 
 

 
function render() { 
 
    gl.clearColor(.25, .5, .75, 1); 
 
    gl.clear(gl.COLOR_BUFFER_BIT); 
 
} 
 

 
function read() { 
 
    const pixel = new Uint8Array(4); 
 
    gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); 
 
    log(pixel); 
 
} 
 

 
function log(...args) { 
 
    const elem = document.createElement("pre"); 
 
    elem.textContent = [...args].join(' '); 
 
    document.body.appendChild(elem); 
 
}
<canvas></canvas>

注意,因爲它的複合操作(瀏覽器實際繪製與HTML其餘頁面上的帆布)觸發清楚,如果畫布不是頁面,則它不會合成並贏得了不會被清除。

換句話說,如果你想調用readPixels在其他一些情況下是沒有上述工作的情況下就在這裏工作

// create an offscreen canvas. Because it's offscreen it won't be composited 
 
// and therefore will not be cleared. 
 
const gl = document.createElement("canvas").getContext("webgl2"); 
 

 
render(); 
 
setTimeout(read, 1000); // read in other event 
 

 
function render() { 
 
    gl.clearColor(.25, .5, .75, 1); 
 
    gl.clear(gl.COLOR_BUFFER_BIT); 
 
} 
 

 
function read() { 
 
    const pixel = new Uint8Array(4); 
 
    gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); 
 
    log(pixel); 
 
} 
 

 
function log(...args) { 
 
    const elem = document.createElement("pre"); 
 
    elem.textContent = [...args].join(' '); 
 
    document.body.appendChild(elem); 
 
}

,當用戶點擊一個元素一樣,那麼你至少有2個選項

  1. preserveDrawingBuffer: true

  2. 在事件再次渲染

    screenshotButton.addEventListener('click',() => { 
        render(); 
        read(); 
    }); 
    

the spec section 2.2

WebGL的介紹其繪製緩衝區到HTML頁面合成立即合成操作之前,但只有當至少有一個從以前的合成操作開始發生以下情況:

  • 上下文創建
  • 帆布調整
  • 清晰,drawArrays,或drawElements被稱爲同時繪製緩衝區是當前綁定的幀緩衝區

繪製緩衝區前提出用於合成實施應確保所有渲染操作已被刷新到繪圖緩衝區。默認情況下,合成後,繪圖緩衝區的內容將被清除爲默認值,如上表所示。

可以通過設置WebGLContextAttributes對象的preserveDrawingBuffer屬性來更改此默認行爲。如果該標誌爲真,則繪圖緩衝區的內容應保留,直到作者清除或覆蓋它們。如果此標誌爲false,則在渲染函數返回後嘗試使用此上下文作爲源圖像執行操作可能會導致未定義的行爲。這包括readPixels或toDataURL調用,或者將此上下文用作另一個上下文的texImage2D或drawImage調用的源圖像。

+0

夢幻般的答案。我假設,即使'preserveDrawingBuffer'設置爲'true'合成需要發生。所以。如何將它設置爲'true'允許'readPixels'以「定義」或一致的方式工作? – Startec

+1

@Startec gman有另外一個很好的答案:https://stackoverflow.com/a/27747016/3190758基本上它的「定義」在於繪圖緩衝區不會被清除爲默認值,而是被複制到顯示緩衝區每次(可能以某些性能爲代價,因爲繪圖和顯示緩衝區不能再被交換) – grovesNL