TextureBufferObjects

Aus DGL Wiki
Wechseln zu: Navigation, Suche

Shader Model 4.0 führt mit der Extension GL_ARB_texture_buffer_object einen zusätzlichen Texturtyp ein: Das TextureBufferObject, oftmals abgekürzt mit TBO. Dabei handelt es sich um eine eindimensionale Textur, welche ihren Speicherbereich nicht selbst enthält, sondern auf den Speicher eines verknüpften BufferObjects zugreift. Bei einem solchen BufferObject kann es sich beispielsweise um ein VertexBufferObject (VBO) handeln. Es steht somit die Flexibilität von Bufferobjekten auch für Texturen zur Verfügung (fast) ohne zusätzliche Schnittstellen.

Im Zusammenhang mit Transform-Feedback aber auch mit Instancing und bei anderen Gelegenheiten erweisen sich TextureBufferObjects als sehr nützlich. Mit Transform-Feedback kann in einen Vertexbuffer geschrieben werden, welcher dann im nächsten Renderpass ohne zusätzliche Kopiervorgänge als Textur benutzt werden kann. Dies wird unter anderem beim Shader Model 4.0 Partikelsystem exzessiv benutzt. Ein Beispiel zu Instancing findet sich in der Shadersammlung.

Im Shader können TextureBufferObjects ausschließlich mit Integer-Koordinaten adressiert werden. Daher findet auch keine Interpolation zwischen Texeln statt. Wer eine Interpolation benötigt kann diese aber einfach selbst im Shader implementieren.

Für TextureBufferObjects muss keine Größe angegeben werden. Die Größe der Textur berechnet sich aus der Gesamtgröße des zugehörigen Bufferobjektes geteilt durch die Größe eines Texels. Die maximale Größe eines TextureBufferObjects beträgt dabei 2^27 = 134.217.728 Texel im Gegensatz zu normalen eindimensionalen Texturen, welche eine maximale Größe von 2^13 = 8.192 Texeln haben. In Kombination mit einem 4x32bit Texelformat (z.B. RGBA32F) bedeutet dies, dass ein TBO theoretisch bis zu 2 GB groß werden darf. Praktisch ist die Größe natürlich durch den Speicher der Grafikkarte begrenzt.

Verwendung

Verwendung im Programm

Um unser TextureBufferObject zu Erstellen benutzen wir wie bei gewöhnlichen Texturen die Funktion glGenTextures:

GLuint myTBO;
glGenTextures(1, &myTBO);

Das Löschen geschieht genauso gewohnt mit glDeleteTextures:

glDeleteTextures(1, &myTBO);

Um das TextureBufferObject zu verwenden muss es wie eine normale Textur mit glBindTexture gebunden werden. Wir übergeben dabei allerdings 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 BufferObject mit dem TextureBufferObject verknüpft werden soll. Bei diesem BufferObject kann es sich zum Beispiel um ein VertexBufferObject handeln.

glTexBufferARB(GL_TEXTURE_BUFFER_ARB, GL_RGBA32F_ARB, myVBO);

Der zweite Parameter gibt hierbei den Datentyp unserer Textur an. Als Beispiel wurde hier GL_RGBA32F_ARB gewählt. Damit wird unsere Textur als vierelementiger 32-bit-float-Vektor benutzt (4*4 = 16 Byte pro Texel). Die Tabelle im Abschnitt Texelformate gibt eine Übersicht über die möglichen Formate, welche als zweiter Parameter angegeben werden können.

Verwendung im Shader

Unser TextureBufferObject 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 TextureBufferObject 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 TextureBufferObject zu:

#extension GL_EXT_gpu_shader4 : require

// ...

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 TextureBufferObject.
	vec4 tmp = texelFetchBuffer(tbo, index); 

	// Wir machen etwas mit tmp
	// ...
}

Texelformate

Die folgende Tabelle aus der Extension-Spezifikation gibt eine Übersicht über die möglichen Texelformate.

Info DGL.png Es gibt 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).
Sized Internal Format Base Type Components Norm Component
0 1 2 3
GL_ALPHA8 ubyte 1 Y A . . .
GL_ALPHA16 ushort 1 Y A . . .
GL_ALPHA16F_ARB half 1 N A . . .
GL_ALPHA32F_ARB float 1 N A . . .
GL_ALPHA8I_EXT byte 1 N A . . .
GL_ALPHA16I_EXT short 1 N A . . .
GL_ALPHA32I_EXT int 1 N A . . .
GL_ALPHA8UI_EXT ubyte 1 N A . . .
GL_ALPHA16UI_EXT ushort 1 N A . . .
GL_ALPHA32UI_EXT uint 1 N A . . .
GL_LUMINANCE8 ubyte 1 Y L . . .
GL_LUMINANCE16 ushort 1 Y L . . .
GL_LUMINANCE16F_ARB half 1 N L . . .
GL_LUMINANCE32F_ARB float 1 N L . . .
GL_LUMINANCE8I_EXT byte 1 N L . . .
GL_LUMINANCE16I_EXT short 1 N L . . .
GL_LUMINANCE32I_EXT int 1 N L . . .
GL_LUMINANCE8UI_EXT ubyte 1 N L . . .
GL_LUMINANCE16UI_EXT ushort 1 N L . . .
GL_LUMINANCE32UI_EXT uint 1 N L . . .
GL_LUMINANCE8_ALPHA8 ubyte 2 Y L A . .
GL_LUMINANCE16_ALPHA16 ushort 2 Y L A . .
GL_LUMINANCE_ALPHA16F_ARB half 2 N L A . .
GL_LUMINANCE_ALPHA32F_ARB float 2 N L A . .
GL_LUMINANCE_ALPHA8I_EXT byte 2 N L A . .
GL_LUMINANCE_ALPHA16I_EXT short 2 N L A . .
GL_LUMINANCE_ALPHA32I_EXT int 2 N L A . .
GL_LUMINANCE_ALPHA8UI_EXT ubyte 2 N L A . .
GL_LUMINANCE_ALPHA16UI_EXT ushort 2 N L A . .
GL_LUMINANCE_ALPHA32UI_EXT uint 2 N L A . .
GL_INTENSITY8 ubyte 1 Y I . . .
GL_INTENSITY16 ushort 1 Y I . . .
GL_INTENSITY16F_ARB half 1 N I . . .
GL_INTENSITY32F_ARB float 1 N I . . .
GL_INTENSITY8I_EXT byte 1 N I . . .
GL_INTENSITY16I_EXT short 1 N A . . .
GL_INTENSITY32I_EXT int 1 N A . . .
GL_INTENSITY8UI_EXT ubyte 1 N A . . .
GL_INTENSITY16UI_EXT ushort 1 N A . . .
GL_INTENSITY32UI_EXT uint 1 N A . . .
GL_RGBA8 ubyte 4 Y R G B A
GL_RGBA16 ushort 4 Y R G B A
GL_RGBA16F_ARB half 4 N R G B A
GL_RGBA32F_ARB float 4 N R G B A
GL_RGBA8I_EXT byte 4 N R G B A
GL_RGBA16I_EXT short 4 N R G B A
GL_RGBA32I_EXT int 4 N R G B A
GL_RGBA8UI_EXT ubyte 4 N R G B A
GL_RGBA16UI_EXT ushort 4 N R G B A
GL_RGBA32UI_EXT uint 4 N R G B A

Literatur