2017-10-07 154 views
1

我正在玩webgl複製從this page。我想用鼠標來控制燈的位置。Webgl - 動態鼠標位置

如果我只是給從js靜態值fragment shader它會工作:

mouseLocation = gl.getUniformLocation(program, "mouse"); 
gl.uniform2f(mouseLocation, 0,0); 

我有一個函數來更新鼠標的位置:

function updateMousePosition(e){ 
    console.log(e.pageX); 
    mousex = e.pageX; 
    mousey = e.pageY; 
} 

被稱爲當鼠標移動:

canvas.addEventListener('mousemove', updateMousePosition, false); 

然後將鼠標位置發送到fragment shader每一幀:

gl.uniform2f(mouseLocation, mousex,mousey); 

之後,我會得到鼠標的位置從fragment shader

uniform vec2 mouse; 

void main(void) { 
    //mp - mouse position 
    vec2 mp = vec2(mouse.x/resolution.x, 1.0 - mouse.y/resolution.y); 

    //lp depend on mp 
    vec3 lp = vec3(mp.x, mp.y, -1.0); 

    //other calculation ... 
} 

沒有奏效。 但是,當我從console.logupdateMousePosition(e)發下來的靜態值:

gl.uniform2f(mouseLocation, 679, 590);//number taken from console.log 

它的工作。

我不確定什麼是不工作,但我懷疑是數字的格式或類型,js是不是嚴格類型,但glsl是。

我該如何解決這個問題?

+0

您需要展示更多代碼。您所展示的內容沒有任何問題。 – gman

回答

0

Finaly決定把這個答案(編輯)。

正如Gman所評論的那樣,您的代碼幾乎沒有任何問題。從技術上講,這應該工作。但是,您指出了與OpenGL相比WebGL/Javascript夫婦的一個非常棘手的方面:樣式。由於Javascript變量的工作原理,您很容易產生奇怪的錯誤。

想象一下這樣的absurde情況:

var x = 55; 
var y = 128; 

// some code here... 

x = "blah"; // oups ! 

// some code here... 

gl.uniform2f(mouseLocation, x, y); 

用C,C++或其他強類型語言,這樣的荒謬幾乎是不可能做到(這是可能通過指針,但這是另一個問題),因爲編譯器嚴格禁止並拋出錯誤。但在JavaScript中,沒有問題,在這種情況下,x數字變量變成字符串變量,並且在傳遞給WebGL時,變成NaN。如果您沒有正確地跟蹤x變量,您將長時間搜索爲什麼這不起作用。

所有的WebGL功能只接受最後階段類型的數據,因爲最後階段是GPU,GPU和低層次的。也就是說,即使你將一個純JavaScript數字變量傳遞給一個WebGL函數,這個Javascript變量也會被轉換爲類型化的數據。但事實是,JavaScript永遠不會拋出關於錯誤變量類型的錯誤:它會將它轉換(轉換)爲類型化數據,即使您嘗試執行的操作是荒謬的,它也不會警告您,它會將不可轉換的數據進入'NaN`。

幸運的是,爲了避免任何歧義,WebGL的配備了一堆新的JavaScript對象:類型化數組:https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/TypedArray

有類型的數組,你可以在你的JavaScript代碼中知道哪些數據存儲,還等什麼數據將在發送之前發送到GPU。 也就是說,您可以使用類型化數組在將數據發送到GPU之前將其轉換(轉換)爲已知的類型化數據。

var mousePos = new Float32Array(2); 

function updateMousePosition(e){ 
    mousePos[0] = e.pageX; 
    mousePos[1] = e.pageY; 
} 

// do something 

console.log(mousePos); 
gl.uniform2fv(mouseLocation, mousePos); 

在上面的例子中,變量e.pageXe.pageY被直接轉換成兼容的WebGL類型化的數據。這樣,如果您現在使用console.log打印mousePos變量,那麼您將看到真正發送給WebGL的內容。爲了進行調試,您可以在撥打gl.uniform2fv之前撥console.log,以確保沒有錯誤發生。

在這個例子中,如果任何數據被錯誤地轉換,你會看到類似NaNNaN在你的輸出日誌,讓你知道,你必須從某個地方尋找錯誤在你的代碼。

+0

我真的很想知道發生了什麼,但忘了更新答案。你的回答是正確的。但是,我的解決方案類似但更簡單。我只是聲明並初始化像var x = 0.0這樣的變量,那麼所有東西都像魅力一樣工作。無論如何,我接受你的答案的細節解釋。 – sooon