2012-03-27 9 views
19

Estoy tratando de estudiar el mapeo de sombra en WebGL. Veo el mismo código de sombreador copiado en varias bibliotecas y ejemplos que logran esto. Sin embargo, en ninguna parte encontré la explicación de cómo funciona.Embalaje flotante en vec4: ¿cómo funciona este código?

La idea es guardar un valor de profundidad (un solo flotante) en el búfer de color (vec4). Hay una función de paquete que guarda float a vec4 y descomprime la función que recupera el float de vec4.

vec4 pack_depth(const in float depth) 
{ 
    const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0); 
    const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0); 
    vec4 res = fract(depth * bit_shift); 
    res -= res.xxyz * bit_mask; 
    return res; 
} 

float unpack_depth(const in vec4 rgba_depth) 
{ 
    const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0); 
    float depth = dot(rgba_depth, bit_shift); 
    return depth; 
} 

me hubiera imaginado que el embalaje de un flotador en vec4 debería ser un problema trivial, simplemente copiarlo en una de las 4 ranuras de vec4 y dejar a otros sin usar. Es por eso que la lógica de cambio de bit en el código anterior me resulta desconcertante.

¿Alguien puede arrojar algo de luz?

Respuesta

12

No está almacenando un GLSL float en un GLSL vec4. Lo que está haciendo es almacenar un valor en un vec4 que, cuando se escribe en un framebuffer RGBA8 (valor de 32 bits) puede leerse como vec4 y luego reconstituirse en el mismo float que se proporcionó anteriormente.

Si hace lo que sugiere, simplemente escribiendo el valor de coma flotante en el canal rojo del framebuffer, obtendrá solo 8 bits de precisión. Con este método, obtienes todos los 32 bits que funcionan para ti.

+0

I see. No era evidente para mí que el búfer de color almacena internamente el valor de color como 4 enteros, aunque lo alimentamos con un vec4. Si eso es así, entonces el código anterior tiene sentido. Gracias. – Jayesh

+0

Estrictamente hablando, la conversión es a un número de punto fijo de 32 bits, no a un número de coma flotante. – Mortennobel

3

Además de la respuesta anterior, que podría estar interesado en la extensión de la textura de punto flotante se describe aquí:

http://www.khronos.org/registry/webgl/extensions/OES_texture_float/

Nota que hay hardware/software configuraciones por ahí donde no existe esta extensión/ejecutar, pero si lo hace seguro es una buena extensión. Mi experiencia es que también es rápido. Si usa esto, puede usar los tres canales restantes para almacenar otra información, como el color de una textura proyectada.

2

Si le interesan los detalles esenciales de cómo funcionan estas rutinas, le sugiero que lea my blog post. Estoy agregando algunos detalles aquí sobre cómo funciona ese código y para abordar algunos posibles casos de uso.

Como probablemente haya averiguado, ese código está codificando un valor flotante normalizado en vec4. OpenGL ES 2.0 o WebGL (en el momento de redactar este documento), podrían usar esas rutinas de empaque/desempaquetado para proporcionar puntos flotantes de precisión de 32 bits a través de las texturas RGBA8 (more on this in the spec).

Incluso con la extensión Publicado por Mikael (OES_texture_float) podría ser necesario (para propósitos de depuración, por ejemplo) para volcar la precisión completa de 32 bits normalizó puntos flotantes y como se describe en la especificación readPixels se encuentra limitado por la siguiente

Solo se aceptan dos combinaciones de formato y tipo. El primero es el formato RGBA y el tipo UNSIGNED_BYTE. El segundo es un formato elegido por la implementación.

Cuestiones relacionadas