2012-03-27 2 views
19

Ich versuche, Shadow Mapping in WebGL zu studieren. Ich sehe das gleiche Stück Shader-Code in verschiedenen Bibliotheken und Beispielen, die dies erreichen. Aber nirgends habe ich die Erklärung dafür gefunden, wie es funktioniert.Float in vec4 verpacken - wie funktioniert dieser Code?

Die Idee besteht darin, einen Tiefenwert (ein einzelnes Float) in den Farbpuffer (vec4) zu speichern. Es gibt eine Paketfunktion, die float in vec4 speichert und die Funktion entpackt, die den float von vec4 abruft.

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

Ich hätte gedacht, dass ein Schwimmer in vec4 Verpackung sollte ein triviales Problem sein, kopieren Sie sie einfach in einen der vier Schlitze von vec4 und andere ungenutzt lassen. Deshalb ist die Bitverschiebungslogik im obigen Code für mich rätselhaft.

Kann jemand etwas Licht abwerfen?

Antwort

12

Es wird kein GLSL float in einem GLSL vec4 gespeichert. Es speichert einen Wert in vec4, der beim Schreiben in einen RGBA8-Framebuffer (32-Bit-Wert) als vec4 gelesen und dann in dasselbe float wiederhergestellt werden kann, das zuvor angegeben wurde.

Wenn Sie das getan haben, was Sie vorschlagen, schreiben Sie einfach den Gleitkommawert in den roten Kanal des Framebuffers, dann erhalten Sie nur 8 Bit Genauigkeit. Mit dieser Methode erhalten Sie alle 32-Bit-Funktionen für Sie.

+0

Ich sehe. Es war mir nicht klar, dass der Farbpuffer intern den Farbwert als 4 ganze Zahlen speichert, obwohl wir ihm einen vec4 geben. Wenn das so ist, dann macht der obige Code Sinn. Vielen Dank. – Jayesh

+0

Genau genommen ist die Umwandlung eine 32-Bit-Festkommazahl - keine Fließkommazahl. – Mortennobel

3

Neben der Antwort oben, können Sie hier beschrieben in der Floating-Point-Textur Erweiterung interessieren:

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

Hinweis, dass es Hardware/Software-Setups dort, wo diese Erweiterung existiert nicht/run, aber wenn es das tut, ist es sicher eine gute Erweiterung. Meine Erfahrung ist, dass es auch schnell ist. Wenn Sie dies verwenden, können Sie die übrigen drei Kanäle zum Speichern anderer Informationen verwenden, z. B. Farbe aus einer projizierten Textur.

2

Wenn Sie sich für die wesentlichen Details der Funktionsweise dieser Routinen interessieren, empfehle ich Ihnen, my blog post zu lesen. Ich füge einige Details dazu hinzu, wie dieser Code funktioniert und um einige mögliche Anwendungsfälle zu behandeln.

Wie Sie wahrscheinlich herausgefunden haben, codiert dieser Code einen normalisierten Gleitkommawert zu vec4. OpenGL ES 2.0 oder WebGL (zum Zeitpunkt des Schreibens), könnte diese Pack/Unpack-Routinen verwenden, um 32-Bit-Präzisions-Fließkommawerte über RGBA8 Texturen (more on this in the spec) bereitzustellen.

Auch bei der Erweiterung von Mikael geschrieben (OES_texture_float) könnte es notwendig sein (für Debug-Zwecke zum Beispiel) dump volle 32-Bit-precision floating Punkte normierte und wie in der Spezifikation beschrieben readPixels ist derzeit begrenzt durch die folgenden

Nur zwei Kombinationen von Format und Typ werden akzeptiert. Der erste ist das Format RGBA und der Typ UNSIGNED_BYTE. Die zweite ist ein von der Implementierung gewähltes Format.