Hi Leute,
ich wollte mal wissen ob es möglich ist, die Pixeldaten einer Textur die schon geladen wurde, nachträglich zu verändern.
Also wenn man nur noch per glBindTexture(GL_TEXTURE_2D, texID) die Textur bindet und die eigentlichen Bilddaten
schon gelöscht wurden.
Hab nämlich im DGL Wiki umhergestöbert und bin auf den Atikel zur Erstellung von Wolken gestoßen. Nicht weit davon
entfernt, war dann die Perlin Noise Funktion. Link: http://wiki.delphigl.com/index.php/Perlin_Noise Nun dachte
ich mir, dass man doch einen schicken, dynamischen Effekt erzeugen könnte, wenn man die aktuell gebundene Textur
zeitabhängig verändern könnte. So könnten dann ja Wolken langsam verschwinden oder wieder neu entstehen ohne
immer eine neue Textur zu erstellen und dann zu laden.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Also ich muss gestehen, dass ich jetzt nicht ganz verstanden habe was du vor hast. Allerdings gibt es verschiedene Befehle zur "Manipulation" von Texturen.
Mit glTexImage kannst du eine komplette Textur hochladen bzw Speicher für eine Textur alloziieren.
Mit glTexSubImage kannst du rechteckige Teile einer Textur überschreiben.
Mit glGetTexImage kannst du die Daten einer Textur zurücklesen. Allerdings dazu solltest du mit glGetTexLevelParameter erst einmal das Format erfragen. Wenn der Treiber der Meinung war er müsse die Textur in einem anderen Format abspeichern, dann kann das schnell zu einem bösen erwachen führen.
Allerdings dauerhaftes Manipulieren der Textur solltest du eher lassen. Für Videos / Streaming von Texturen ist es üblich, dass die Texturen häufig geändert werden muss aber sonst würde ich versuchen dort einen anderen Weg zu finden. Denn in deinem Fall müsstest du wäre das berechnen einer neuen Textur vermutlich recht umständlich und außerdem muss die Textur dann noch hochgeladen werden. Und wärend der Zeit kann die GPU nur eines tun. Und zwar Warten.
Wenn du deine Wolken mit Perlin Noise machen willst, dann würde ich schon sagen, dass du die Wolken nur in Kackeln berechnen solltest und nur diese Kacheln dann beim Zeichnen verschieben. Wenn Kacheln nicht mehr sichtbar sind solltest du sie dann löschen. Der Vorteil dabei ist, dass du nicht dauerhaft irgendwelche Texturen berechnen müsstest. Das kostet zwar etwas mehr Speicher aber würde unmengen an Rechenleistung einsparen.
PS: Evtl würden auch tilebare Texturen etwas für dich sein. Diese könntest du einfach immer und immer wiederholen ohne, dass es ein Ende geben würde. Wenn die Texturen nicht zu klein sind würde evtl sogar auch schon ausreichen.
Danke, die von dir erwähnten Funktionen, scheinen in die richtige Richtung zu gehen. Da ich das Ganze nicht extrem
rechenaufwändig gestalten will (falls es doch ziemlich rechenaufwändig ist, bitte bescheid sagen), hier mal meine
Vorstellung, wie man vorgehen könnte. Anstatt der Noise Funktion kann man ja auch einfach irgendwelche
Texturen mit Gimp erstellen um die Vorgehensweise zu testen.
- Daten einlesen, Texturen erstellen
- mit glTexLevelParameteriv Format erfragen
- Pixeldaten beider Bilder per glGetTexImage einhohlen
- Daten in ein Array schreiben
- per Random die nächste TexID auswählen.
- Pixeldaten(Array) von Textur1 mit Textur2 verrechnen um heraus zu
finden um wieviel sich jedes Pixel aus Textur1 erhöhen / verringern muss
pro Renderdurchlauf, um in einer gewissen Zeit Textur2 zu ergeben.
- Pixeldaten von Textur1 bei jeden Durchlauf entsprechend verändern
- wenn fertig, **** Zeit abwarten und von vorne beginnen
Jetzt könnte man auf die Idee kommen Multitexturing oder Blending zu benutzen, aber das erzeugt nicht den Effekt den
ich erzeugen möchte. (um es schon mal zu erwähnen ^^) Meine erste Frage richtet sich an glGetTexImage. Hier übergibt
man als letzten Parameter den Rückgabewert (laut Wiki: Liefert das Texturbild. pixels ist ein Pointer auf ein Feld vom Typ type. )
Wenn es ein Pointer ist und ich die Daten in dem Array verändere, verändere ich doch auch automatisch die Pixeldaten von der Textur und brauche somit glTexSubImage gar nicht, oder ?!
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
glGetTexImage: Ja du übergibst einen Pointer. ABER einen Pointer in den die Methode die Texturdaten schreibt. Die Texturen liegen in einem komplett anderen Speicherbereich. Dort kannst du nicht direkt darauf zugreifen. Wenn es so einfach wäre, dann kann ich dir als Pointerfanatiker versichern, dass ich das schon 1-20 mal gemacht hätte.
Zu deinem eigentlichen Problem. Dazu werde ich mich gerade geschlossen halten, da ich denke, dass du ein wenig mehr ins Detail gehen solltest. Ich kann nicht genügend abschätzen was du da genau vor hast um dir Tipps zu geben hinter denen ich 100%tig stehe. Da fehlt mir ein bisschen Hintergrundwissen was du genau vor hast. Im Zweifel gerne auch mit Bildern.
glGetTexImage: Ja du übergibst einen Pointer. ABER einen Pointer in den die Methode die Texturdaten schreibt. Die Texturen liegen in einem komplett anderen Speicherbereich.
... verdammt ^^
Wie komme ich dann an diesen Speicherbereich ?
Ich würde ja gerne Bilder zur Veranschaulichung zeigen, aber wenn ich das könnte, dann hätte ich ja auch kein Problem mehr. ^^
Es sollten aber mehrere Bilder (z.B. 4 Stück) sein die alle in etwa so aussehen wie von http://freespace.virgin.net/hugo.elias/models/m_clouds.htm.
Normalerweise müsste ich nur eine Textur von einem Bild im Speicher erstellen und von den anderen 3 Bildern brauche ich nur die Pixeldaten in einem Array. Denn die Texturen werden ja nicht ausgetauscht, sondern die Pixeldaten einer Textur werden immer wieder verändert. Während das erste Bild normal (z.B. auf einem Quad) angezeigt wird, wird alle ** Sekunden per Random eines der Arrays mit den Pixeldaten ausgewählt. Nun soll die Textur aber nicht gleichmäßig an allen Stellen mit dem Alphakanal überblendet werden, sondern die Differenz zwischen jeden Pixel aus dem Alphakanal der aktuellen Textur mit der als nächstes folgenden in ein extra Array geschrieben werden.
Die Differenz wäre 200. Das wird dann noch durch die Zeit geteilt in der die Pixeldaten der aktuellen Textur durch den neuen Wert ersetzt werden sollen. Danach kann man bei jeden Renderdurchlauf oder FPS Count (codeabhängig) den Wert erhöhen oder verringern um so das neue Bild zu erzeugen. Nach ** Sekunden geht das Spielchen von vorne los.
Das die Vorstellung zur Zeit noch alles andere als perfekt ist, ist mir klar, aber an dem System sollte sich nicht so viel verändern. Ich will halt die Pixeldaten von 3 verschiedenen Bildern einlesen in ein Array und immer die Pixeldaten der aktuellen Textur zeitabhängig verändern.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Screenshot?
R2-D2: Also wenn ich das Richtig verstanden habe, dann hast du 4+ Bilder (ich sage bewusst nicht Textur dazu) und in Abhängigkeit der Zeit möchtest du zwischen diesen Bilden überblenden und daraus ein Bild erstellen was du als Textur benutzt um es auf dem Bildschirm darzustellen? Sehe ich das Richtig? Wenn nein, dann vergiss das was ich gleich schreiben werde.
Die Rohdaten bräuchtest du gar nicht als Textur. Denn du stellst ja sowieso immer nur eine fertig berechnete Textur dar. Also brauchst du einen Speicherbereich der deiner Textur entspricht und dort würdest du die neue Textur hineinrechnen. Je nachdem wie weit fortgeschritten die Zeit ist. Anschließend kannst du mit glTexSubImage die Daten in deine vorhandene Textur schreiben und beim nächsten Zeichnen würde sie dann anders aussehen. Dort gibt es meiner Meinung nach keine Notwendigkeit irgendwelche Texturen wieder auszulesen. Du brauchst einige Daten ja so oder so nur im RAM und entsprechend solltest du diese dann auch nur im RAM halten. Vom RAM gibts sowieso mehr als Texturspeicher.
PS: "Wie komme ich dann an diesen Speicherbereich?" Gar nicht. An den Speicherbereich kommst du nicht. Du kannst nur etwas in ein OpenGL Objekt (Textur) hineinschreiben oder wenn es sein muss auch auslesen. Aber direkt auf den Speicher kannst du nicht zugreifen.
Danke für den Tip, aber der Artikel setzt voraus, dass ich den kompletten Bildschirm kopieren möchte oder ich immer weiß, wo mein Objekt sich im Raum befindet (um nur die Daten der Textur auf dem Objekt einzulesen) . Ich möchte aber direkt die Pixeldaten einer Textur verändern. Sprich sie aus- und einlesen. Zwischendurch natürlich manipulieren.
Mein Problem könnte man auch als Lösungsansatz für ein Bitmap Font Loader benutzen(in abgewandelter Form).
Man hat eine Haupttextur auf der die ganzen Pixeldaten der Buchstaben liegen und erstellt eine zweite, leere Textur die, die Pixeldaten der eingegebenen Zeichenkette später aufnehmen soll. Für jeden eingegebenen Buchstaben gibt es eine 2D-Koordinate die auf einen Bereich des Buchstabens innerhalb der Haupttextur zeigt. Dort werden dann die Pixeldaten in ein Array eingelesen und in der zweiten, (bis jetze noch) leeren Textur an der gewünschten Stelle eingelesen. Danach kann man die erstellte Textur benutzen um über ein Quad den gewünschten Text anzuzeigen.
Vlt. klingt ja mein Problem so etwas verständlicher. ^^
// EDIT : Da war jemand schneller
Zitat:
Die Rohdaten bräuchtest du gar nicht als Textur. Denn du stellst ja sowieso immer nur eine fertig berechnete Textur dar.
Richtig, einmal im Speicher eine Textur und 3 Arrays die die Pixeldaten der anderen Bilder enthalten. Mit diesen Arrays sollen dann die Daten der Textur verändert werden. Sry falls man es nicht rauslesen konnte.
Registriert: Sa Jan 01, 2005 17:11 Beiträge: 2068
Programmiersprache: C++
Steht im Screenshot nicht die Methode über RenderToTexture und dann auslesen?
Dachte ich zumindest.
Die beste Methode sind hier Shader. Wieso?
Naja, Grafikkarten sind eigentlich Einbahnstrassen und das Auslesen dauert lange.
Bei glGetTexImage ist die Frage woher du den Pointer 'pixels' bekommst?
Den erstellst du mit GetMem(Dimension des Bildes) bzw. ein entsprechend grosses (dynamisches) Array.
Da ich mich noch nicht mit Shadern auskenne, bevorzuge ich vorerst glTexSubImage. Da kommt aber auch schon die Frage:" Wie nutze ich den Befehl ?!"
Probiere schon die ganze Zeit hin und her und der Code verändert die aktuelle Textur einfach nicht.
Also ein Array für glGetTexImage brauche ich nicht da ich mit SDL arbeite und die Pixeldaten immer noch im Surface habe und mir den Schritt sparen kann.
Mache es folgendermaßen:
Ich erstelle ganz normal eine Textur. Das Texturformat(texformat) und die Bytes Pro Pixel(bpp) werden im Code weiter oben ermittelt.
Danach folgt das:
Als Pixeldaten übergebe ich 0 da ich ja noch keine Daten hineinschreiben will. Dann möchte ich einfach nur innerhalb einer Schleife glTexSubImage2D anwenden und möglichst Schritt für Schritt die oben erstellte Textur mit Pixeldaten füllen. X und Y verändern sich immer um die Position anzugeben wo sich die Daten befinden.
Code:
glTexSubImage2D(texID, 0, x, y, cellwidth, cellwidth, texformat, GL_UNSIGNED_BYTE, font->pixels);
Aber es passiert einfach nichts. glTexSubImage2D wird komplett ignoriert.
Ich habe also in einem Surface die Pixeldaten, erstelle eine leere Textur die kleiner als die Pixeldaten aus dem Surface sind und fülle
dann die Textur mit einzelnen Bruchstücken des Surfaces. Soweit die Planung, funktionieren tut es aber nicht.
Bitte sagt mir einer wie das geht.
Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.