2012-02-27 48 views
4

我使用Three.js將3D模型繪製到簡單DOM元素上方的webgl畫布渲染器上,並且我需要在它們之間進行碰撞檢測。我目前的工作方法是使用renderer.domElement.toDataURL(),將其作爲imageData對象加載,然後將其繪製到單獨的2D畫布上下文中,然後拉出getImageData()像素數組並迭代使用this awesome pixel collision function是一個imageData CanvasPixelArray直接可用於畫布WebGL上下文嗎?

這是難以置信慢,下來拉我的幀速率幾乎不可再現〜5-8 FPS。沒有運行這個命中檢測,我得到大約40-50 FPS。

我最好的猜測是減速是令人難以置信的難以忍受的toDataURL() - >加載圖像 - > drawImage() - > getImageData()

我的問題變成:有沒有更好的方式來訪問WebGL畫布上可用的平面化2D像素數據?或者也許更好的方法來推斷我的3D對象座標沒有視差?老實說,任何能比我現在做的更快地獲得某種碰撞檢測的方法將非常有用。

編輯:WebGL的context.readPixels()對我的作品偉大,並與我以前的雜牌是超級快。儘管應該指出,與常規圖像像素數據陣列相比,數據陣列是從上到下鏡像的。我簡單地翻轉了我的碰撞程序Y值檢查並得到了這個工作,儘管其他人可能會以更棘手的方式絆倒。祝你好運!

回答

4

您可以使用gl.readPixels

// Render your scene first then... 
var left = 0; 
var top = 0; 
var width = canvas.width; 
var height = canvas.height; 
var pixelData = new Uint8Array(width * height * 4); 
gl.readPixels(left, top, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelData); 

PixelData取出現在包含場景的像素數據爲無符號字節(0-255)佈局爲[R, G, B, A, R, G, B, A...]應該是相同的數據getImageData,但在低得多的成本。

[編輯:]

我忘了提,如果你打算做這個,你會想與preserveDrawingBuffer選項創建WebGL的情況下,像這樣:

var gl = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true}); 

這可以防止WebGL的內部工作在清除緩衝區之前清除緩衝區(這會導致您讀取大量空像素)。啓用此選項可能會減慢渲染速度,但它的加載速度仍應高於5-8 FPS! :)

+0

不錯!我很驚訝,我之前忽略了這一點。這個「有效」,但是..如果你將這些數據繪製回另一個畫布上來查看它,它是從上到下鏡像的!任何簡單的方法來翻轉你可以想到的?我可能只是在我的碰撞檢測程序中翻轉我的Y ... – TechNinja 2012-02-29 01:52:17

+0

如果你想要一個簡單的方法來保存順序,你可以創建另一個畫布。使用第一個作爲drawImage的源,然後使用getImageData作爲臨時的。 – 2016-08-24 20:03:40

0
renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer:true }); 



var gl = renderer.getContext() 
var buf = new Uint8Array(200 * 200 * 4); 
gl.readPixels(0, 0, 200, 200, gl.RGBA, gl.UNSIGNED_BYTE, buf); 


console.log(buf); 

這工作正常。