TextureBufferObjects: Unterschied zwischen den Versionen
K-bal (Diskussion | Beiträge) (Artikel erstellt!) |
K-bal (Diskussion | Beiträge) K (→Benutzung seitens der CPU: (gl)BindTexture, gl ergänzt) |
||
Zeile 27: | Zeile 27: | ||
− | Zuerst binden wir das Texture Buffer Object wie eine normale Textur mit '' | + | Zuerst binden wir das Texture Buffer Object wie eine normale Textur mit ''glBindTexture(enum target, uint texture)''. Wir übergeben die Konstante ''GL_TEXTURE_BUFFER_ARB'' als ersten Parameter: |
<source lang="cpp"> | <source lang="cpp"> | ||
Zeile 101: | Zeile 101: | ||
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). | 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 === | === Benutzung seitens der GPU === |
Version vom 7. Januar 2010, 22:26 Uhr
Inhaltsverzeichnis
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 glBindTexture(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