supports que org mac khronos for docs opengl-es webgl glsles

opengl es - que - ¿Cómo convierto entre float y vec4, vec3, vec2?



webgl que es (3)

He escrito un pequeño ejemplo hace unos días con shadertoy: https://www.shadertoy.com/view/XdK3Dh

Almacena float como RGB o carga flotante desde un píxel. También hay pruebas de que la función son inversas exactas (muchas de las otras funciones que he visto tienen errores en algunos rangos debido a la mala precisión).

Todo el ejemplo supone que desea guardar valores en el búfer y volver a leerlos en el siguiente sorteo. Tener solo 256 colores, te limita a obtener 16777216 valores diferentes. La mayoría de las veces no necesito una escala mayor. También lo moví para tener firmado el flotador insted en el intervalo <-8388608; 8388608>.

float color2float(in vec3 c) { c *= 255.; c = floor(c); // without this value could be shifted for some intervals return c.r*256.*256. + c.g*256. + c.b - 8388608.; } // values out of <-8388608;8388608> are stored as min/max values vec3 float2color(in float val) { val += 8388608.; // this makes values signed if(val < 0.) { return vec3(0.); } if(val > 16777216.) { return vec3(1.); } vec3 c = vec3(0.); c.b = mod(val, 256.); val = floor(val/256.); c.g = mod(val, 256.); val = floor(val/256.); c.r = mod(val, 256.); return c/255.; }

Una cosa más, los valores que se desbordan se redondean al valor mínimo / máximo.

Esta pregunta está muy relacionada con la pregunta aquí ( ¿Cómo convierto un valor vecg rgba en un flotante? ).

Ya hay algunos artículos o preguntas relacionados con esta pregunta, pero me pregunto si la mayoría de los artículos no identifican qué tipo de valor flotante. Siempre y cuando se me ocurra, a continuación encontrará una fórmula de embalaje / desembalaje de valor flotante.

  • flotador normalizado sin signo
  • Flotador normalizado firmado
  • flotación a distancia con signo (el valor flotante puedo encontrar limitación de rango)
  • flotador a distancia sin signo
  • flotador sin signo
  • flotador firmado

Sin embargo, estos son solo 2 casos en realidad. El otro embalaje / desembalaje puede procesarse con estos 2 métodos.

  • Flotador a distancia sin signo (Puedo empaquetar / desempaquetar fácilmente mediante cambio de bits)
  • flotador firmado

También quiero empacar y descomprimir los valores flotantes firmados en vec3 o vec2.

Para mi caso, el valor flotante no está garantizado para ser normalizado, así que no puedo usar el modo simple de cambio de bits.


Si conoce el rango máximo de valores que desea almacenar, digamos de +5 a -5, entonces la manera más fácil es simplemente elegir convertir ese rango a un valor de 0 a 1. Expanda eso al número de bits que tiene y luego divídelo en partes.

vec2 packFloatInto8BitVec2(float v, float min, float max) { float zeroToOne = (v - min) / (max - min); float zeroTo16Bit = zeroToOne * 256.0 * 255.0; return vec2(mod(zeroToOne, 256.0), zeroToOne / 256.0); }

Para volver a ponerlo, haces lo contrario. Arme las partes, divídalas para volver a un valor de cero a uno, luego amplíelas por el rango.

float unpack8BitVec2IntoFloat(vec2 v, float min, float max) { float zeroTo16Bit = v.x + v.y * 256.0; float zeroToOne = zeroTo16Bit / 256.0 / 255.0; return zeroToOne * (max - min) + min; }

Para vec3 solo expandirlo

vec3 packFloatInto8BitVec3(float v, float min, float max) { float zeroToOne = (v - min) / (max - min); float zeroTo24Bit = zeroToOne * 256.0 * 256.0 * 255.0; return vec3(mod(zeroToOne, 256.0), mod(zeroToOne / 256.0, 256.0), zeroToOne / 256.0 / 256.0); } float unpack8BitVec3IntoFloat(vec3 v, float min, float max) { float zeroTo24Bit = v.x + v.y * 256.0 + v.z * 256.0 * 256.0; float zeroToOne = zeroTo24Bit / 256.0 / 256.0 / 256.0; return zeroToOne * (max - min) + min; }


Para empaquetar un valor de punto flotante en un vec2 , vec3 o vec4 , el rango de los valores fuente debe estar restringido y bien especificado, o el exponente también debe almacenarse de alguna manera.
En general, si los dígitos significativos de un número de coma flotante deben empacarse en bytes, consecutivamente, los paquetes de 8 bits deben extraerse de los dígitos significativos y deben almacenarse en un byte.


Codifique un número de punto flotante en un rango restringido y predefinido

Debe definirse un rango de valores [ minVal , maxVal ] que incluya todos los valores que se codificarán y el rango de valores debe asignarse al rango de [0.0, 1.0].

Codificación de un número de coma flotante en el rango [ minVal , maxVal ] a vec2 , vec3 y vec4 :

vec2 EncodeRangeV2( in float value, flaot minVal, maxVal ) { value = clamp( (value-minVal) / (maxVal-minVal), 0.0, 1.0 ); value *= (256.0*256.0 - 1.0) / (256.0*256.0); vec3 encode = fract( value * vec3(1.0, 256.0, 256.0*256.0) ); return encode.xy - encode.yz / 256.0 + 1.0/512.0; } vec3 EncodeRangeV3( in float value, flaot minVal, maxVal ) { value = clamp( (value-minVal) / (maxVal-minVal), 0.0, 1.0 ); value *= (256.0*256.0*256.0 - 1.0) / (256.0*256.0*256.0); vec4 encode = fract( value * vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) ); return encode.xyz - encode.yzw / 256.0 + 1.0/512.0; } vec4 EncodeRangeV4( in float value, flaot minVal, maxVal ) { value = clamp( (value-minVal) / (maxVal-minVal), 0.0, 1.0 ); value *= (256.0*256.0*256.0 - 1.0) / (256.0*256.0*256.0); vec4 encode = fract( value * vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) ); return vec4( encode.xyz - encode.yzw / 256.0, encode.w ) + 1.0/512.0; }

Descodificación de un vec2 , vec3 y vec4 a un número de coma flotante en el rango [ minVal , maxVal ]:

float DecodeRangeV2( in vec2 pack, flaot minVal, maxVal ) { float value = dot( pack, 1.0 / vec2(1.0, 256.0) ); value *= (256.0*256.0) / (256.0*256.0 - 1.0); return mix( minVal, maxVal, value ); } float DecodeRangeV3( in vec3 pack, flaot minVal, maxVal ) { float value = dot( pack, 1.0 / vec3(1.0, 256.0, 256.0*256.0) ); value *= (256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0); return mix( minVal, maxVal, value ); } float DecodeRangeV4( in vec4 pack, flaot minVal, maxVal ) { float value = dot( pack, 1.0 / vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) ); value *= (256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0); return mix( minVal, maxVal, value ); }

Nota: Dado que un número IEEE 754 estándar de 32 bits tiene solo 24 dígitos significativos, es completamente suficiente codificar el número en 3 bytes.


Codifique los dígitos significativos y el exponente de un número de punto flotante

Codificación de los dígitos significativos de un número de punto flotante y su exponente a vec2 , vec3 y vec4 :

vec2 EncodeExpV2( in float value ) { int exponent = int( log2( abs( value ) ) + 1.0 ); value /= exp2( float( exponent ) ); value = (value + 1.0) * 255.0 / (2.0*256.0); vec2 encode = fract( value * vec2(1.0, 256.0) ); return vec2( encode.x - encode.y / 256.0 + 1.0/512.0, (float(exponent) + 127.5) / 256.0 ); } vec3 EncodeExpV3( in float value ) { int exponent = int( log2( abs( value ) ) + 1.0 ); value /= exp2( float( exponent ) ); value = (value + 1.0) * (256.0*256.0 - 1.0) / (2.0*256.0*256.0); vec3 encode = fract( value * vec3(1.0, 256.0, 256.0*256.0) ); return vec3( encode.xy - encode.yz / 256.0 + 1.0/512.0, (float(exponent) + 127.5) / 256.0 ); } vec4 EncodeExpV4( in float value ) { int exponent = int( log2( abs( value ) ) + 1.0 ); value /= exp2( float( exponent ) ); value = (value + 1.0) * (256.0*256.0*256.0 - 1.0) / (2.0*256.0*256.0*256.0); vec4 encode = fract( value * vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) ); return vec4( encode.xyz - encode.yzw / 256.0 + 1.0/512.0, (float(exponent) + 127.5) / 256.0 ); }

Descodificación de un vec2 , vec3 y vec4 para los dígitos significativos de un número de punto flotante y su exponente:

float DecodeExpV2( in vec2 pack ) { int exponent = int( pack.z * 256.0 - 127.0 ); float value = pack.x * (2.0*256.0) / 255.0 - 1.0; return value * exp2( float(exponent) ); } float DecodeExpV3( in vec3 pack ) { int exponent = int( pack.z * 256.0 - 127.0 ); float value = dot( pack.xy, 1.0 / vec2(1.0, 256.0) ); value = value * (2.0*256.0*256.0) / (256.0*256.0 - 1.0) - 1.0; return value * exp2( float(exponent) ); } float DecodeExpV4( in vec4 pack ) { int exponent = int( pack.w * 256.0 - 127.0 ); float value = dot( pack.xyz, 1.0 / vec3(1.0, 256.0, 256.0*256.0) ); value = value * (2.0*256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0) - 1.0; return value * exp2( float(exponent) ); }


Ver también las respuestas a las siguientes preguntas: