Pythonstuff GLSL in English Pythonstuff GLSL auf Deutsch Pythonstuff GLSL Pythonstuff
PythonStuff Home
 

 

Beispiel 3 - GLSL Texture Maps

Aufbauend auf dem vorigen Beispiel wird die Oberfläche texturiert.

Das Ergebnis sieht so aus:

Texture Mapped Torus Texture Mapped Torus - das Licht etwas bewegt Texturierte Kugel

Die Textur befindet sich im Texture Pack.

Um die Demo ablaufen zu lassen, benötigt man Pyglet und Tristam Macdonald's Modul Shader.py. Alles findest Du auch auf der Installationsseite.

Programmbeschreibung

Um auf der Objektoberfläche eine Textur darzustellen, muß ein entsprechendes Bild in den Speicher der Grafikkarte geladen werden. Das Management dieser Bilder ist durch die Verwendung von Pyglet-Ressourcen am einfachsten zu bewerkstelligen:

resource.path.append('textures')
resource.reindex()
texturecnt = 1

Wir machen das Unterverzeichnis “textures” bekannt, auf das mit

textureSurface = pyglet.resource.texture(texturefile)

zugegriffen werden kann. Das wir bereits im nächsten Beispiel mehr als ein Bild benötigen, benutzen wir die Variable “texturecnt” sowohl zum Laden der Resourcen (einstellbare Anzahl von Texturen “Texturemap<x>.jpg”), als auch um den entsprechende Verknüpfung (“bind”) mit dem Shader-Programm herzustellen:

...
texture = []
for i in range (texturecnt):
    texturefile = 'Texturemap' + str(i) + '.jpg'
    print "Loading Texture", texturefile
    textureSurface = pyglet.resource.texture(texturefile)
    texture.append( textureSurface.get_texture() )
    glBindTexture(texture[i].target, texture[i].id)
...
for i in range(texturecnt):
  glActiveTexture(GL_TEXTURE0+i)
  glEnable(GL_TEXTURE_2D)
  glBindTexture(GL_TEXTURE_2D, texture[i].id)
  shader.uniformi('my_color_texture[' + str(i) + ']',i )
...

Im Shader-Programm selbst sieht die Deklaration so aus:

uniform sampler2D my_color_texture['''+str(texturecnt)+''']; // 0 = ColorMap
uniform int toggletexture; // false/true

Da das Shaderprogramm hier als Triple-Quote-String im Python eingebettet ist, “unterbrechen” wir den String und setzen den (statischen) Wert “texturecnt” ein.

Im Fragment-Shader können wir dann die Farbe einer bestimmten Position der Textur auslesen mit:

vec4 texColor = texture2D(my_color_texture[0], gl_TexCoord[0].st);

Diese Farbe ersetzt den konstanten Wert aus dem letzten Beispiel - wir müssen uns nur noch die Textur-Koordinaten, also die richtige Stelle im Textur-Bild beschaffen.

Dazu erweitern wir die Vertex-Daten um die Textur-Koordinaten, die für u und v jeweils von 0..1 laufen:

textureuvw.extend([u / (2 * pi), v / (2 * pi), 0.0])

(u und v laufen für die Generierung der Figur von 0..2*pi, daher die Division).

Dieses Array wird beim Erzeugen der Vertex-Liste mit

...
('t3f/static', textureuvw),
...

übergeben und im Vertex-Shader der “varying” Standardvariable “gl_TexCoord[0]” zugewiesen:

gl_TexCoord[0]  = gl_TextureMatrix[0] * gl_MultiTexCoord0

Damit ist jetzt klar, wie der Zugriff mittels

vec4 texColor = texture2D(my_color_texture[0], gl_TexCoord[0].st);

funktioniert.

Das Ein- und Ausschalten der Textur steuern wir über die “T”-Taste, mit der im vorigen Beispiel die Umschaltung zwischen Wireframe und Fläche gemacht wurde:

...
elif symbol == key.T:
    toggletexture = not toggletexture
    print 'Toggle Texture ', toggletexture
...

Diese Variable wird an den Fragment-Shader übergeben - bei “False” wird texColor wie im vorigen Beispiel auf einen konstanten Wert gesetzt:

if ( toggletexture == 0 ) texColor = gl_FrontMaterial.ambient;

Dazu kommt jetzt Bump Mapping !


English version, Start
Impressum & Disclaimer