TextureBufferObjects

Aus DGL Wiki
Version vom 7. Januar 2010, 22:24 Uhr von K-bal (Diskussion | Beiträge) (Artikel erstellt!)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Texture Buffer Objects

Einleitung Das Shader Model 4.0 bietet einen neuen Texturtyp, die Texture Buffer Objects (GL_ARB_texture_buffer_object). Diese sind eindimensionale Texturen, welche ihren Speicherbereich nicht selbst enthalten, sondern auf den Speicher eines verknüpften Buffer Objects zugreifen. Es steht somit die Flexibilität von Bufferobjekten auch für Texturen zur Verfügung (fast) ohne zusätzliche Schnittstellen. So kann zum Beispiel mit Transform Feedback in einen Vertexbuffer geschrieben werden, welcher im nächsten Renderpass wiederum ohne zusätzliche Kopiervorgänge als Textur benutzt werden kann. Dies wird unter anderem beim Shader Model 4.0 Partikelsystem exzessiv benutzt.


Erstellung und Löschung

Um unser Texture Buffer Object zu erstellen benutzen wir die Funktion glGenTextures(sizei count, uint* texturehandles):

GLuint myTBO;
glGenTextures(1, &myTBO);

Das Löschen geschieht mit glDeleteTextures(sizei count, uint* texturehandles):

glDeleteTextures(1, &myTBO);


Benutzung seitens der CPU

Zuerst binden wir das Texture Buffer Object wie eine normale Textur mit BindTexture(enum target, uint texture). Wir übergeben die Konstante GL_TEXTURE_BUFFER_ARB als ersten Parameter:

glBindTexture(GL_TEXTURE_BUFFER_ARB, myTBO);

Anschließend geben wir mit glTexBufferARB(enum target, enum internalformat, uint buffer) an, welches Buffer Object mit dem Texture Buffer Object verknüpft werden soll:

glTexBufferARB(GL_TEXTURE_BUFFER_ARB GL_RGBA32F_ARB, myVBO);

Der zweite Parameter gibt hierbei den Datentyp unserer Textur an. Als Beispiel ist hier GL_RGBA32F_ARB gewählt. Damit wird unsere Textur als vierelementiger 32-bit-float-Vektor benutzt (4*4 = 16 byte pro Texel). Folgende Tabelle aus der OpenGL-Spezifikation gibt eine Übersicht über die möglichen Konstanten, welche als zweiter Parameter angegeben werden können:

                                                            Component
     Sized Internal Format     Base Type  Components  Norm   0 1 2 3
     ------------------------  ---------  ----------  ----   -------
     ALPHA8                     ubyte         1        Y     A . . .
     ALPHA16                    ushort        1        Y     A . . .
     ALPHA16F_ARB               half          1        N     A . . .
     ALPHA32F_ARB               float         1        N     A . . .
     ALPHA8I_EXT                byte          1        N     A . . .
     ALPHA16I_EXT               short         1        N     A . . .
     ALPHA32I_EXT               int           1        N     A . . .
     ALPHA8UI_EXT               ubyte         1        N     A . . .
     ALPHA16UI_EXT              ushort        1        N     A . . .
     ALPHA32UI_EXT              uint          1        N     A . . .
     LUMINANCE8                 ubyte         1        Y     L . . .
     LUMINANCE16                ushort        1        Y     L . . .
     LUMINANCE16F_ARB           half          1        N     L . . .
     LUMINANCE32F_ARB           float         1        N     L . . .
     LUMINANCE8I_EXT            byte          1        N     L . . .
     LUMINANCE16I_EXT           short         1        N     L . . .
     LUMINANCE32I_EXT           int           1        N     L . . .
     LUMINANCE8UI_EXT           ubyte         1        N     L . . .
     LUMINANCE16UI_EXT          ushort        1        N     L . . .
     LUMINANCE32UI_EXT          uint          1        N     L . . .
     LUMINANCE8_ALPHA8          ubyte         2        Y     L A . .
     LUMINANCE16_ALPHA16        ushort        2        Y     L A . .
     LUMINANCE_ALPHA16F_ARB     half          2        N     L A . .
     LUMINANCE_ALPHA32F_ARB     float         2        N     L A . .
     LUMINANCE_ALPHA8I_EXT      byte          2        N     L A . .
     LUMINANCE_ALPHA16I_EXT     short         2        N     L A . .
     LUMINANCE_ALPHA32I_EXT     int           2        N     L A . .
     LUMINANCE_ALPHA8UI_EXT     ubyte         2        N     L A . .
     LUMINANCE_ALPHA16UI_EXT    ushort        2        N     L A . .
     LUMINANCE_ALPHA32UI_EXT    uint          2        N     L A . .
     INTENSITY8                 ubyte         1        Y     I . . .
     INTENSITY16                ushort        1        Y     I . . .
     INTENSITY16F_ARB           half          1        N     I . . .
     INTENSITY32F_ARB           float         1        N     I . . .
     INTENSITY8I_EXT            byte          1        N     I . . .
     INTENSITY16I_EXT           short         1        N     A . . .
     INTENSITY32I_EXT           int           1        N     A . . .
     INTENSITY8UI_EXT           ubyte         1        N     A . . .
     INTENSITY16UI_EXT          ushort        1        N     A . . .
     INTENSITY32UI_EXT          uint          1        N     A . . .
     RGBA8                      ubyte         4        Y     R G B A
     RGBA16                     ushort        4        Y     R G B A
     RGBA16F_ARB                half          4        N     R G B A
     RGBA32F_ARB                float         4        N     R G B A
     RGBA8I_EXT                 byte          4        N     R G B A
     RGBA16I_EXT                short         4        N     R G B A
     RGBA32I_EXT                int           4        N     R G B A
     RGBA8UI_EXT                ubyte         4        N     R G B A
     RGBA16UI_EXT               ushort        4        N     R G B A
     RGBA32UI_EXT               uint          4        N     R G B A

Wie man sieht, gibt es nur ein-, zwei- und vier-elementige Typen. Will man also drei-elementige Daten benutzen, so muss man eine vierte Komponente ergänzen (zusätzlicher Speicherverbrauch) oder die Komponenten-Indizes im Shader zurückrechnen (zusätzlicher Rechenaufwand).


Benutzung seitens der GPU

Unser Texture Buffer Object ist nun erstellt und gebunden. Nun ist es an der Zeit, es im Shader auszulesen. Dafür brauchen wir neue Textursampler-Typen: samplerBuffer, usamplerBuffer oder isamplerBuffer, je nachdem, was unser Texture Buffer Object für einen Datentyp repräsentiert: float, unsigned int oder int. Über diesen Sampler greifen wir mit der Funktion texelFetchBuffer(samplerBuffer sampler, uint index) auf unser Texture Buffer Object zu:

 
// .....

uniform samplerBuffer tbo;  // Unser sampler, wir benutzen floats => samplerBuffer

void main() 
{ 
	// Wir brauchen einen Array-Index um einen Texel zum Auslesen zu bestimmen.

	unsigned int index;

	// Wir berechnen unseren Index.

	// ....
	
	// Wir holen einen Texel aus unserem Texture Buffer Object.

	vec4 tmp = texelFetchBuffer(tbo, index); 

	// Wir machen etwas mit tmp

	// .....
}


Größe

Für Texture Buffer Objects muss keine Größe angegeben werden; Die Größe der Textur berechnet sich aus der Gesamtgröße des zugehörigen Buffer Objektes geteilt durch die Größe eines Texels. Die maximale Größe eines Texture Buffer Objects beträgt dabei 2^27 = 134217728 im Gegensatz zu normalen eindimensionalen Texturen, welche eine maximale Größe von 2^13 = 8192 haben.


Literatur

http://www.opengl.org/registry/specs/ARB/texture_buffer_object.txt