Webgl - 动态鼠标位置
我正在玩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.log
在updateMousePosition(e)
发下来的静态值:
gl.uniform2f(mouseLocation, 679, 590);//number taken from console.log
它的工作。
我不确定什么是不工作,但我怀疑是数字的格式或类型,js
是不是严格类型,但glsl
是。
我该如何解决这个问题?
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.pageX
和e.pageY
被直接转换成兼容的WebGL类型化的数据。这样,如果您现在使用console.log
打印mousePos
变量,那么您将看到真正发送给WebGL的内容。为了进行调试,您可以在拨打gl.uniform2fv
之前拨console.log
,以确保没有错误发生。
在这个例子中,如果任何数据被错误地转换,你会看到类似NaN
,NaN
在你的输出日志,让你知道,你必须从某个地方寻找错误在你的代码。
我真的很想知道发生了什么,但忘了更新答案。你的回答是正确的。但是,我的解决方案类似但更简单。我只是声明并初始化像var x = 0.0这样的变量,那么所有东西都像魅力一样工作。无论如何,我接受你的答案的细节解释。 – sooon
您需要展示更多代码。您所展示的内容没有任何问题。 – gman