类型化数组(包括Float32Arrays)只是压缩数组(想想C/C++)。更新它们是即时的。如果你想在GPU上看到数据,你必须用texImage2D再次上传数据,否则,就没有魔法,没有疯狂的缓冲,非常直接。如果你知道C/C++,它在功能上等价于
void*arrayBuffer=malloc(sizeOfBuffer);float*viewAsFloat=(float*)arrayBuffer;
类型化数组不是JS数组的视图。使用本机JS数组初始化类型化数组只是初始化类型化阵列的一种方便方法。一旦创建,TypedArray就是一个新数组。
不过,您可以将多个ArrayBuffer视图放入同一个Array Buffer中。
例子
var b=新的ArrayBuffer(16);//制作一个16字节的ArrayBuffervar bytes=新Uint8Array(b);//在ArrayBuffer中创建Uint8Array视图var longs=新Uint32Array(b);//在ArrayBuffer中创建Uint32Array视图var floats=新的Float32Array(b);//在ArrayBuffer中创建Float32Array视图//打印视图的内容console.log(字节);console.log(longs);console.log(浮点);//使用其中一个视图更改字节字节[1]=255;//再次打印内容console.log(字节);console.log(longs);console.log(浮点);
将所有代码复制并粘贴到JavaScript控制台中。你应该看到这样的东西
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 0, 0] [0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [65280, 0, 0, 0] [9.1447676375112406e-41,0,0,0]
注意:使用多个视图不同类型的在同一阵列上的缓冲区不兼容跨平台。换句话说,在大端平台和小端平台上会得到不同的结果。目前还没有支持TypedArrays的浏览器的流行大端平台,所以您可以忽略这个问题,尽管您的页面可能会在未来的平台上中断。如果要以独立于平台的方式读/写数据,应使用数据视图否则,在同一缓冲区上使用多个视图的主要目的是上传打包的顶点数据,例如用uint32 RGBA颜色打包的浮点位置。在这种情况下,它将跨平台工作,因为您没有使用视图读/写相同的数据。
如前所述,JS本机数组和TypedArrays没有关系,除非您可以使用JS本机数组初始化TypedArray
var jsArray=[1,2,3,4];var floats=新的Float32Array(jsArray);//这是一个新数组,而不是视图。console.log(jsArray);console.log(浮点);jsArray[1]=567;//仅影响JS数组console.log(jsArray);console.log(浮点);浮点数[2]=89;//仅影响浮点数组console.log(jsArray);console.log(浮点);
粘贴到控制台中
[1, 2, 3, 4] [1, 2, 3, 4] [1, 567, 3, 4] [1, 2, 3, 4] [1, 567, 3, 4] [1, 2, 89, 4]
注意,您可以从任何类型的数组中获取底层ArrayBuffer。
var buffer=floats.buffer;
并创建新视图
var longs=新Uint8Array(缓冲区);console.log(longs);//打印[0,0,128,63,0,0,0,64,0,0178,66,0,0,128,64]
您还可以创建覆盖缓冲区一部分的视图。
var偏移=8;//偏移量以字节为单位var长度=2;//长度以类型为单位//查看最后2个浮点的缓冲区var f2=新的Float32Array(缓冲区、偏移量、长度);控制台日志(f2);//打印[89,4]
至于纹理和类型化数组,这里有一个使用Float32Array更新浮点纹理的片段。
main();函数main(){var canvas=文档.getElementById(“canvas”);var gl=canvas.getContext(“webgl”);如果(!gl){警报(“无WebGL”);回报;}var f=gl.getExtension(“OES_texture_float”);如果(!f){警报(“无OES_texture_float”);回报;}var程序=twgl.createProgramFromScripts(gl,[“2d-vertex-shader”,“2d-fragment-shader”]);gl.useProgram(程序);var positionLocation=gl.getAttribLocation(程序,“a_position”);var resolutionLocation=gl.getUniformLocation(程序,“u_resolution”);gl.uniform2f(分辨率位置、画布宽度、画布高度);var缓冲区=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,缓冲区);gl.bufferData(gl.ARRAY_BUFFER,新的Float32Array([-1, -1, 1, -1, -1, 2,-1、1、1,-1、1、1]),gl.STATIC_DRAW);gl.enableVertexAttribArray(位置位置);gl.vertexAttribPointer(位置位置,2,gl.FLOAT,false,0,0);var-tex=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,tex);var宽度=64;var高度=64;var像素=新的Float32Array(宽度*高度*4);对于(var y=0;y<高度;++y){for(var x=0;x<宽度;++x){var偏移=(y*宽度+x)*4;像素[偏移量+0]=(x*256/宽度)*1000;像素[偏移量+1]=(y*256/高度)*1000;像素[偏移量+2]=(x*y/(宽度*高度))*1000;像素[偏移+3]=256000;}}gl.tex图像2D(gl.TEXTURE_2D,0,gl.RGBA,宽度,高度,0,gl.RGBA,像素);gl.tex参数(gl.TEXTURE_2D,gl.TESTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D、gl.TEXTURE_WRAP_T、gl.CCLAMP_TO_EDGE);gl.tex参数(gl.TEXTURE_2D,gl.TESTURE_MIN_FILTER,gl.NEAREST);gl.tex参数(gl.TEXTURE_2D,gl.TESTURE_MAG_FILTER,gl.NEAREST);函数randInt(范围){return Math.floor(Math.random()*range);}函数render(){//更新随机像素var x=randInt(宽度);var y=randInt(高度);var偏移=(y*宽度+x)*4;像素[偏移量+0]=randInt(256000);像素[偏移量+1]=randInt(256000);像素[偏移量+2]=randInt(256000);gl.tex图像2D(gl.TEXTURE_2D,0,gl.RGBA,宽度,高度,0,gl.RGBA,像素);gl.drawArrays(gl.TRIANGLES,0,6);requestAnimationFrame(渲染);}渲染();}
<script src=“https://twgljs.org/dist/2.x/twgl.min.js“></script><script id=“2d-vertex-shader”type=“x-shader/x-vertex”>属性vec2 a_position;空main(){gl_Position=vec4(a_Position,0,1);}</script><script id=“2d-fragment-shader”type=“x-shader/x-fragment”>精密介质浮子;均匀vec2 u_resolution;均匀采样器2D u_tex;空main(){vec2 texCoord=gl_FragCoord.xy/u_resolution;vec4 floatColor=纹理2D(u_tex,texCoord);gl_FragColor=floatColor/256000.0;}</script><canvas id=“canvas”width=“400”height=“300”></cavas>
所有这些都表明你所看到的问题可能与其他问题有关?至于调试,如上所述,ArrayBuffer非常简单,没有延迟缓冲或任何东西。因此,如果您想查看ArrayBuffer,请为其创建一个视图,这样调试器就可以知道您想要显示什么。