2017-10-07 129 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