gpt4 book ai didi

JavaScript TypedArray 混合类型

转载 作者:行者123 更新时间:2023-11-28 14:34:08 25 4
gpt4 key购买 nike

我正在尝试使用 WebGL,并希望将一些不同的类型混合到一个字节缓冲区中。我知道 TypedArrays 可以达到这个目的,但不清楚我是否可以与它们混合类型(OpenGL 顶点数据通常是与无符号字节或整数混合的 float )。

在我的测试中,我想使用 set() 将 2 个 float 打包到 UInt8Array 中,但它似乎只是将 2 个 float 放入了前 2 个元素中UInt8Array。当然,我希望它能填充数组,因为我们有 8 个字节的数据。

有没有办法在 JavaScript 中实现这一点,或者我是否需要将所有顶点数据保留为 float ?

src = new Float32Array(2); // 2 elements = 8 bytes
src[0] = 100;
src[1] = 200;

dest = new UInt8Array(8); // 8 elements = 8 bytes
dest.set(src, 0); // insert src at offset 0

dest = 100,200,0,0,0,0,0,0 (only the first 2 bytes are set)

最佳答案

您可以通过在同一缓冲区上创建不同的 View 来混合类型。

const asFloats = new Float32Array(2);
// create a uint8 view to the same buffer as the float32array
const asBytes = new Uint8Array(asFloats.buffer);

console.log(asFloats);
asBytes[3] = 123;
console.log(asFloats);

TypeArrays 真正的工作方式是有一个叫做 ArrayBuffer 的东西,它有一定的字节长度。要查看字节,您需要一个 ArrayBufferView,其中有各种类型 Int8ArrayUint8ArrayInt16ArrayUint16ArrayInt32ArrayUint32ArrayFloat32ArrayFloat64Array

您可以从头开始创建ArrayBuffer

const buffer = new ArrayBuffer(8);
const asFloats = new Float32Array(buffer);
asFloats[0] = 1.23;
asFloats[1] = 4.56;
console.log(asFloats);

或者您可以做更正常的事情,即创建特定类型的 ArrayBufferView ,它将创建该类型的ArrayBufferView/strong> 如果您不将其传递给构造函数,也会为其创建 ArrayBuffer。然后,您可以从 someArrayBufferView.buffer 访问该缓冲区,如上面第一个示例所示。

您还可以为 View 分配 ArrayBuffer 中的偏移量和长度,以使其小于 ArrayBuffer。示例:

// make a 16byte ArrayBuffer and a Uint8Array (ArrayBufferView)
const asUint8 = new Uint8Array(16);

// make a 1 float long view in the same buffer
// that starts at byte 4 in that buffer
const byteOffset = 4;
const length = 1; // 1 float32
const asFloat = new Float32Array(asUint8.buffer, byteOffset, length);

// show the buffer is all 0s
console.log(asUint8);

// set the float
asFloat[0] = 12345.6789

// show the buffer is affected at byte 4
console.log(asUint8);

// set a float out of range of its length
asFloat[1] = -12345.6789; // this is effectively a no-op

// show the buffer is NOT affected at byte 8
console.log(asUint8);

因此,如果您想为 WebGL 混合 float 位置和 Uint8 颜色,您可能会执行类似的操作

// we're going to have
// X,Y,Z,R,G,B,A, X,Y,Z,R,G,B,A, X,Y,Z,R,G,B,A,
// where X,Y,Z are float32
// and R,G,B,A are uint8

const sizeOfVertex = 3 * 4 + 4 * 1; // 3 float32s + 4 bytes
const numVerts = 3;
const asBytes = new Uint8Array(numVerts * sizeOfVertex);
const asFloats = new Float32Array(asBytes.buffer);

// set the positions and colors
const positions = [
-1, 1, 0,
0, -1, 0,
1, 1, 0,
];
const colors = [
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
];
{
const numComponents = 3;
const offset = 0; // in float32s
const stride = 4; // in float32s
copyToArray(positions, numComponents, offset, stride, asFloats);
}
{
const numComponents = 4;
const offset = 12; // in bytes
const stride = 16; // in bytes
copyToArray(colors, numComponents, offset, stride, asBytes);
}

console.log(asBytes);
console.log(asFloats);

function copyToArray(src, numComponents, offset, stride, dst) {
const strideDiff = stride - numComponents;
let srcNdx = 0;
let dstNdx = offset;
const numElements = src.length / numComponents;
if (numElements % 1) {
throw new Error("src does not have an even number of elements");
}
for (let elem = 0; elem < numElements; ++elem) {
for(let component = 0; component < numComponents; ++component) {
dst[dstNdx++] = src[srcNdx++];
}
dstNdx += strideDiff;
}
}

关于JavaScript TypedArray 混合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50289008/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com