我正在玩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
。
我该如何解决这个问题?
答案 0 :(得分:0)
Finaly决定把这个答案(编辑)。
正如Gman评论的那样,您的代码显然没有任何问题。从技术上讲,这应该有效。然而,与OpenGL相比,你指出了WebGL / Javascript夫妇的一个真正棘手的方面:典型。由于Javascript变量的工作原理,您很容易产生奇怪的错误。
想象一下这种荒谬的情况:
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 Number变量传递给WebGL函数,此Javascript变量也会转换为之前的类型化数据。但事实是Javascript永远不会抛出关于错误变量类型的错误:它将它(转换)转换为类型化数据,即使你试图做的是荒谬的,它也永远不会警告你,它会转换不可转换的数据进入' NaN`。
幸运的是,为了避免任何歧义,WebGL附带了一堆新的Javascript对象:Typed Arrays:https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/TypedArray
使用类型化数组,您可以在javascript代码中知道存储的数据,以及在发送数据之前将哪些数据发送到GPU。 也就是说,您可以使用类型化数组将Javascript变量转换(转换)为已知类型数据,然后再将其发送到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兼容的类型数据。这样,如果您现在使用mousePos
打印console.log
变量,您将看到将真正发送到WebGL的内容。出于调试目的,您可以在调用console.log
之前放置gl.uniform2fv
以确保没有发生任何错误"在视图之外"。
在此示例中,如果错误地转换了任何数据,您会在输出日志中看到类似NaN
,NaN
的内容,因此您知道必须在代码中搜索错误。