29

WebGL 着色器语言 (GLSL) 是一个非常强大的多维向量数学工具。

是否有可能使用 JavaScript(在 Web 浏览器中运行)的强大功能进行私人非 3D 计算?获取数据是可能的,但是在着色器计算完成后有什么方法可以将数据输出到 JavaScript 中?

不需要实际绘图,只需要计算向量。(我在玩用 JavaScript 编写的硬件加速重力模拟器的想法。)

谢谢你!


新闻中:Khronos 似乎正在开发WebCL,它将成为OpenCL的 JavaScript 可访问版本。这正是我正在寻找的,但需要一些时间......

4

3 回答 3

17

据我从规范中可以看出, WebGL 支持帧缓冲区对象和回读操作。这足以让您转换数据并将其返回到客户端空间。下面是一系列操作:

  1. 使用您需要存储结果的附件渲染缓冲区创建 FBO;绑定它
  2. 将所有输入数据上传到纹理中(相同大小)。
  3. 创建 GLSL 处理着色器,它将在片段部分内进行演算,从纹理读取输入并将输出写入目标渲染缓冲区;绑定它
  4. 画一个四边形;通过 读回渲染缓冲区glReadPixels
于 2011-03-24T13:24:19.017 回答
6

从浏览器的着色器中获取浮点数实际上非常简单,但约束是每像素 1 个浮点数。

我们将 4 个 int 转换为 1 个 float (r: int, g: int, b: int, a: int) -> (rgba: float)。

感谢 IEEE

float random(vec2 seed) { 
    return fract(cos(mod(123456780., 1024. * dot(seed / time, vec2(23.1406926327792690, 2.6651441426902251))))); 
}
float shift_right(float v, float amt) { 
    v = floor(v) + 0.5; return floor(v / exp2(amt)); 
}
float shift_left(float v, float amt) { 
    return floor(v * exp2(amt) + 0.5); 
}
float mask_last(float v, float bits) { 
    return mod(v, shift_left(1.0, bits)); 
}
float extract_bits(float num, float from, float to) { 
    from = floor(from + 0.5); to = floor(to + 0.5); 
    return mask_last(shift_right(num, from), to - from); 
}
vec4 encode_float(float val) { 
    if (val == 0.0) return vec4(0, 0, 0, 0); 
    float sign = val > 0.0 ? 0.0 : 1.0; 
    val = abs(val); 
    float exponent = floor(log2(val)); 
    float biased_exponent = exponent + 127.0; 
    float fraction = ((val / exp2(exponent)) - 1.0) * 8388608.0; 
    float t = biased_exponent / 2.0; 
    float last_bit_of_biased_exponent = fract(t) * 2.0; 
    float remaining_bits_of_biased_exponent = floor(t); 
    float byte4 = extract_bits(fraction, 0.0, 8.0) / 255.0; 
    float byte3 = extract_bits(fraction, 8.0, 16.0) / 255.0; 
    float byte2 = (last_bit_of_biased_exponent * 128.0 + extract_bits(fraction, 16.0, 23.0)) / 255.0; 
    float byte1 = (sign * 128.0 + remaining_bits_of_biased_exponent) / 255.0; 
    return vec4(byte4, byte3, byte2, byte1); 
}

用法:

着色器:

outputcolor = encode_float(420.420f);

JavaScript:

// convert output to floats
output = new Float32Array(output.buffer);
于 2014-03-12T18:02:01.940 回答
2

是的,这是可行的——这里有一个 Aaron Babcock 的旧演示(可能需要一些调整才能使其在 1.0 WebGL 规范上工作)。

于 2011-03-24T14:19:00.107 回答