C++ OpenGL Texturen?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Texturen in OpenGL sind ein durchaus anspruchsvolles Thema. Ihre Verwendung in einem Programm verlangt einige Vorarbeit und und die Beachtung etlicher Details.

Eine Textur ist entweder ein Bild oder eine rechnerisch erzeugte Bitmap. Höhe und Breite einer Textur müssen Potenzen von 2 sein; Bilder müssen in der Regel zugeschnitten werden um diese Anforderung zu erfüllen.

Eine Textur wird auf die Oberfläche eines Körpers aufgezogen. Dazu ist es erforderlich, einen Zusammenhang herzustellen zwischen Punkten auf der Oberfläche des Körpers und Punkten in der Textur. Hierzu dienen Texturekoordinaten.

Zur Erinnerung:

Ein Körper wird in OpenGL durch ein aus Raumpunkten gebildetes Gitter beschrieben. Dabei werden mit den Gitterpunkten Dreiecke gebildet. In modernem OpenGL werden die Raumpunkte in einem eindimensionalen Array bereitgestellt; die Definition der Dreiecke geschieht in einem weiteren Array, das Punktindices enthält. Meist wird ein drittes Array bereitgestellt, das die Normalenvektoren des Raumkörpers an allen Raumpunkten des Gitters enthält. Die Normalenvektoren werden nur gebraucht, wenn man das Aussehen eines Szeneobjekts durch Beleuchtung mit farbigem Licht gestalten möchte.

In sehr alten Versionen von OpenGL konnten Körper mit einem "direct drawing" genannten verfahren gezeichnet werden, die folgen der Zeichengefehle begann mit glBegin() und endet mit glEnd(). Auf dieses Bilderzeugungsverfahren will ich jetzt nicht weiter eingehen.

Wenn man auf eine Raumfläche eine Textur auftragen will, muss man für alle Raumpunkte der Raumfläche zusätzlich die sogenannten Texturkoordinaten angeben. Die Texturkoordinaten stellen eine Beziehung her zwischen einem Punkt auf der Raumfläche und einem Punkt in der Textur.

Für die Festlegung der Texturkoordinaten muss man wissen: Über die ganze Textur wird ein Koordinatensystem gelegt, das sowohl in der x-Richtung als auch in der y-Richtung von 0 bis 1 läuft.

Wenn man eine Textur nur einmal auf die Raumfäche auftragen will, kommen in den Texturkoordinaten sowohl für den x-Wert als auch für den y-Wert nur Werte zwischen 0 und 1 vor. Wenn man für die Texturkoordinaten konstante Inkremente wählt, schafft man es, eine Textur verzerrungsfrei auf eine Ebene aufzutragen, deren Gitterpunkte ebenfalls mit konstanten Inkrementen bestimmt wurden.

Wenn man eine Textur wiederholt auf eine Raumfläche auftragen will, sind die Werte der Texturkoordinaten nicht mehr auf das Intervall [0, 1] beschränkt. Außerdem muss man die Texturparameter GL_TEXTURW_WARP_S und GL_TEXTURE_WRAP_T beide auf GL_REPEAT setzen. Das erledigt man mit Aufrufen von glTexParameteri.

Die Kombination der Farbwerte von Raumfläche und Textur geschieht im Fragmentshader, wo mit der Funktion texture auf den Farbwert der Textur zugegriffen wird. Die Kombination der Farbwerte kann auf verschiedene Weise geschehen; die Multiplikation der Farbwerte entspricht dem, was in OpenGL 1.x durch die Funktion GL_MODULATE geleistet wurde.

Hier findest du zwei Beispiele, die beide das gleiche Szeneobjekt zeigen: Eine doppelseitig gefärbte, animierte Raumfläche, für die durch Eingabe des Buchstaben 't' eine Textur eingeschaltet oder ausgeschaltet werden kann. DurchEingabe des Buchstabens 'p' kannst du zwischen einer Parallelperspektive und einer Zentralperspektive umschalten.

https://github.com/bg-hub/OpenGL33-GLFW-Texture-Example01 (für OpenGL 3.3)

https://github.com/bg-hub/OpenGL45-GLFW-Texture-Example01 (für OpenGL 4.5)

Beide Beispiele unterscheiden sich nur in der Konfiguration des GLFW-Fensters für OpenGL 3.3 bzw. für OpenGL 4.5. OpenGL 3.3 sollte auf allen halbwegs modernen Arbeitsplatzrechnern ausführbar sein und neuere Grafikkarten können natürlich auch OpenGL 4.5.

Diese Beispile sind für Linux vorbereitet, wenn du sie auf Windows mit glad ablaufen lassen willst, wirst du in der Datei main.cpp wohl die Verwendung von glad einfügen müssen. Die Beispiele verwenden GLM, was eigentlich Stadard ist, wenn man OpenGL mit C++ verwendet.

( siehe: https://glm.g-truc.net/0.9.2/api/index.html und https://github.com/g-truc/glm).

Woher ich das weiß:Berufserfahrung – Berufstätigkeit als Software-Entwickler

Das ist etwas komplizierter. Dafür verwendest du beispielsweise Sampler:

https://www.khronos.org/opengl/wiki/Sampler_(GLSL)

https://www.khronos.org/opengl/wiki/Sampler_Object

Du erstellst dir Host(CPU)-seitig ein Sampler-Objekt mit zugehörigem Speicher, dem du eine Textur zuweist. Bei Aufrufen deines Shaders bindest du den entsprechenden Sampler an einen Texture-Slot.

Client(GPU)-seitig kannst du dann als Uniform einen Sampler in deinem Shader deklarieren und diesen mit verschiedenen Funktionen verwenden, um auf die Textur zuzugreifen.

Wie du die Textur dann auf dein Objekt bekommst ist Anwendungsabhängig. Normalerweise dürftest du Texture-Koordinaten für dein Objekt haben, die du verwendest, um aus der texture die Farbe zu lesen, die du dann für die Beleuchtungsberechnung verwendest oder Ähnliches.

Oldscool. Soweit ich das noch in Erinnerung habe mapst Du das Pixelbild mit 3D Vektoren also Du erstellst dir eine Rendering Engine, die Pixel mit Helligkeit abstimmt. Verdeckte Pixel brauchst Du nicht berechnen. Das würde nur bremsen. Leider sind meine alten Beispiele verloren gegangen wo ich es hinbekommen habe ein Bild mit gdi zu rendern, das war aber C#.

Woher ich das weiß:Hobby
theCPP 
Fragesteller
 14.06.2022, 12:22

Ich meine irgendeine Funktion

0
Destranix  15.06.2022, 14:24

Ich glaube du hast da irgendetwas anderes vor Augen, als der Fragensteller vermutlich erfragen möchte.

0