tutorial shadertoy shaders boy javascript math matrix glsl webgl

javascript - shadertoy - glsl tutorial



Usando WebGL Shader Language(GLSL) para matemáticas de vectores arbitrarios en JavaScript (3)

WebGL Shader Language (GLSL) es una herramienta muy poderosa para matemáticas vectoriales multidimensionales.

¿Hay alguna posibilidad de usar esa potencia desde JavaScript (ejecutándose en el navegador web) para cálculos privados que no sean en 3D? Obtener datos es posible, pero ¿hay alguna manera de obtener datos en JavaScript una vez que se hayan realizado los cálculos del sombreado?

No es necesario un dibujo real, solo calcula vectores. (Estoy jugando con una idea del simulador de gravedad acelerado por hardware escrito en JavaScript.)

¡Gracias!

En las noticias: Khronos parece estar desarrollando WebCL que será una versión accesible de JavaScript de OpenCL . Eso es exactamente lo que estoy buscando, pero llevará algo de tiempo ...


Obtener flotadores de un sombreador en el navegador es bastante fácil, sin embargo, la restricción es de 1 flotante por píxel.

Convertimos 4 ints en 1 float (r: int, g: int, b: int, a: int) -> (rgba: float).

Gracias 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); }

Uso:

Shader:

outputcolor = encode_float(420.420f);

JavaScript:

// convert output to floats output = new Float32Array(output.buffer);


Por lo que puedo ver en las spec WebGL admite objetos de framebuffer y operaciones de lectura. Esto es suficiente para que pueda transformar los datos y recuperarlos en el espacio del cliente. Aquí hay una secuencia de operaciones:

  1. Cree FBO con búferes de renderizado de adjuntos que necesita para almacenar el resultado; atarlo
  2. Cargue todos los datos de entrada en texturas (del mismo tamaño).
  3. Cree el sombreador de procesamiento GLSL que hará el cálculo dentro de la parte del fragmento, leyendo la entrada de texturas y escribiendo la salida en los renderbuffers de destino; atarlo
  4. Dibuja un quad; lee los búferes de renderización a través de glReadPixels .

Sí, es factible: hay una demo anterior (podría necesitar algunos ajustes para que funcione con la especificación 1.0 WebGL) de Aaron Babcock here .