OpenGL vbo erstellen/ausgeben

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

PhillipK

Betreff: OpenGL vbo erstellen/ausgeben

BeitragDo, Jul 14, 2011 6:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Heyho Leute!

Meine Lernexkursion hat Opengl erreicht.

Ich versuche dort grade, eine 2D tilemap zu erstellen.
An sich, die map, habe ich schon. Allerdings nutze ich glBegin() ; glEnd(); blöcke, um 12280 Quads auf dem Bildschirm auszugeben.
Das war mir (logischerweise) etwas zu doof Very Happy

An sich lief es mit etwa 140fps, relativ konstant. Aber ich will mehr.

Nachdem ich verschiedene verbesserungen eingebaut hab, habe ich mich dennoch dazu entschieden, endlich mal VBO zu lernen und dies einzusetzen.

------------------

Meine Landschaft ist in Sektoren unterteilt, welche je 64x64 kacheln halten.
Zu jedem Sektor wollte ich nun ein VBO erstellen, welches mir das Zeichnen schneller machen soll Smile Smile

Als vertexinformationen brauche ich U,V, Farbe(RGB), XY koordinaten, packe aber gleich Z mit rein.

Nach dem durchforsten verschiedenste Tutorials, verschiedenster Sprachen und auch konsultieren von Vertex' beispiel von 2005 (glaube ich^^), verstehe ich nurnoch bahnhof.

Grundlegend sollte ich die Struktur verstanden haben, aber ich fürchte, ich bin einfach zu doof Very Happy

Unterteilen wir also mal:

Erstellen:
BlitzMax: [AUSKLAPPEN]
		glGenBuffersARB(1, Varptr(Self.vbo[0])) 'neuen Buffer anlegen
glBindBufferARB(GL_ARRAY_BUFFER, Self.vbo[0]) 'buffer binden um ihn zu nutzen.

'Größe der vertexdaten:
Local iSize:Int = 64 * 64 * 4 * 5
'Größe der farbdaten: (häää?)
Local colSize:Int = 64 * 64 * 4 * 3

Self.vboArr = New Float[iSize + colSize]

Self.vboArr soll ebenfalls die Vertexdaten halten, sodass ich später, falls ich was ändern möchte, den Array einfach neu in die Grafikkarte kopieren muss. Zumindest stand es auf diese weise in irgnem Tutorial und klang ganz nützlich Very Happy -> Darum ist der array den ich fülle (mit meinen Vertexdaten) auch als Field im sektor abgelegt.

64 * 64 * 4 * 5 und 64 * 64 * 4 *3 habe ich so berechnet:
64x64 kacheln sind klar. Jede hat 4 eckpunkte (nein, ich möchte NOCH keinen indexarray verwenden! das ist mir noch zu hoch!). *5 für: U,V,X,Y,Z
Das selbe spiel von vorn, nur mit *3 für Colordaten.

Dann beginnt das spiel mit dem Array füllen:

BlitzMax: [AUSKLAPPEN]
	'vertex1!
vboArr[vboSize + 0] = 0.0
vboArr[vboSize + 1] =.25
vboArr[vboSize + 2] = color
vboArr[vboSize + 3] = color
vboArr[vboSize + 4] = color
vboArr[vboSize + 5] = xpos
vboArr[vboSize + 6] = ypos
vboArr[vboSize + 7] = 0.0
vboSize:+8


Ich gehe in 2 verschachelten For-schleifen (x und y position im Sektorinternen Array) die positionen der Kacheln durch und werde hier später ein paar andere Werte eintragen.

Color ist local deklariert, wird mit einem Farbwert gefüllt (Soll eine art helligkeit wiederspiegeln).
xpos,ypos berechne ich anhand der Position des Sektors und der Kachel. Die stimmt Smile
Der letzte eintrag nach xpos/ypos ist die Z-Koordinate, da ich die aber noch nicht nutzen möchte, ist sie 0. Smile



Nundenn, füllen abgeschlossen.

Nun der letzte Part des erstellens:

BlitzMax: [AUSKLAPPEN]
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vboSize * 4, Self.vboArr, GL_STATIC_DRAW_ARB) 


vboSize wird in den For-schleifen hochgezählt. sollte soweit passen :< *4 soll für 4Byte stehen. Da ich floats verwende, nehme ich einfach mal an, das 4 byte pro wert belegt sind Smile

3te parameter wäre mein eben gefüllter FLOAT ARRAY. (Sollte ich hier VarPtr(self.vboArr[0]) anwenden? Immerhin erwartet die funktion einen Byte ptr Sad )

Nunjut, dann hätten wir noch das Zeichnen:
BlitzMax: [AUSKLAPPEN]
	Method Draw()
glEnableClientState(GL_VERTEX_ARRAY) ;

glBindBufferARB(GL_ARRAY_BUFFER_ARB, Self.vbo[0]) ;
glInterleavedArrays(GL_T2F_C3F_V3F, 8 * SizeOf(GL_FLOAT), Null)
glDrawArrays(GL_QUADS, 0, 64 * 64*4)


glDisableClientState(GL_VERTEX_ARRAY)

End Method


Hier bin ich mir ganz und garnicht sicher.
Ich nutze InterleavedArrays, um möglichst wenig fehlerquellen einzubauen und nicht mit mehreren Arrays hantieren muss.
Wie gesagt, ich möchte es erstmal lernen Smile Danach kann ich immernoch verbessern.
Als buffer gebe ich den gespeicherten Buffer-index an, welcher beim füllen des VBO's gesetzt+gebunden wurde.

glInterleavedArrays() teile ich die reihenfolge mit: U,V, R,G,B, X,Y,Z
Danach kommt stride - womit ich überhaupt nichts anfangen kann.
Jedesmal wenn ich mti dem wert rumspiele, passiert irgendwas komisches :< Die definitionen von Stride, die ich so im inet gefunden habe, sind nicht mit meinem lächerlichen Englisch zu vereinen - es klingt fast als wolle man den Offset zwischen einem Vertex zum nächsten haben :> Darum: 8*4 (u,v,r,g,b,x,y,z = 8 * 4 Byte)

-------------------
Lange rede kurzer sinn:

Viele sachen verwirren mich. Zb gibt es anscheinend 3-4 Methoden ein VBO zu nutzen und zu füllen. Ich denke ich habe mir die simpelste rausgesucht, allerdings vllt auch die performancelastigste.
Ich habe es eben zum ersten mal (seit 3 tagen!) geschafft, ein VBO anzeigen zu lassen. Allerdings enthält dieser nur EINE KACHEL pro sektor, teilweise auch überhaupt nur eine Einzige.
Ich verstehe einfach nicht, wo ich meinen fehler gemacht habe - es wird ja was angezeigt oO

Wenn ich mit den Stride-werten rumspiele, erhalte ich kuriose ergebnisse. Eben habe ichs sogar geschafft, meinen pc zu quählen. (Viele lustige punkte auf dem Bild, auf Windows, beim herunterfahren etc^^ - zum glück gings nach einem Neustart wieder weg). Nun bin ich etwas vorsichtiger und schreibe lieber erstmal an die Profis :<

Ich hoffe, es gibt irgendjemanden, der sich das alles angetan hat und mir evtl helfen kann Smile

Mfg, PhillipK


Edit 14.07.2011 - 06:43:

Ohje, so ein mist!

Ich habe den fehler eingegrenzt - es ist doch nicht nur eine kachel pro sektor zu sehen! Anscheinend ist der abstand zwischen den Kacheln viel zu groß.
Könnte heißen, das die positionsangaben verfuscht sind, oder? Sad

Nun, das zwischen -1 und 1 zu berechnen sollte nicht das ding sein, aber wieso ist das so?

Meine totalen koordinaten angaben funktionieren auch mit glVertex2f(xpos,ypos) !

Edit 14.07.2011 - 08:16:

Okay ich habe meinen fehler weiter eingegrenzt.
Meine xpos und ypos konnte ich so ganz gut für meine glBegin() - glEnd() blöcke nutzen, allerdings nicht für vbo.

Ich versuche grade, das ganze auf eine glTranslated() verschiebung umzuschreiben, dann mittlerweile sehe ich alle sektoren (denke ich)

Gibt es weitere eigenheiten die im zusammenspiel mit VBO zu beachten sind?
Und warum genau kann ich keine genau errechneten XY positionen nutzen? Gibts dafür einen grund oder habe ich einfach schlampig gearbeitet?

Noobody

BeitragDo, Jul 14, 2011 9:15
Antworten mit Zitat
Benutzer-Profile anzeigen
PhillipK hat Folgendes geschrieben:
Nun, das zwischen -1 und 1 zu berechnen sollte nicht das ding sein, aber wieso ist das so?

Koordinaten im Bereich zwischen -1 und 1 sind Gerätekoordinaten - das klingt also sehr danach, als ob deine Vertices untransformiert an den Rasterizer weitergereicht werden. Bist du dir sicher, dass du eine korrekte orthogonale Projektionsmatrix aufgesetzt hast? Kannst du uns am besten den ganzen Code zeigen (oder zumindest alles, was mit OGL zu tun hat)?
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

PhillipK

BeitragDo, Jul 14, 2011 10:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Der gesamte Code wäre ein wenig viel *g*
Es besteht quasie alles aus OGL befehlen.

Ich habe mir die Zeit genommen und alles vereinfacht. Es ist mir nun möglich, VBO's richtig darzustellen.
Grund sind meine Verschiebungskoordinaten gewesen, warum kann ich allerdings nicht erklären.

BlitzMax: [AUSKLAPPEN]
Local ypos:Int = y * tileSize + (Self.y * (SekPixelSize)) + a
Local xpos:Int = x * tileSize + (Self.x * (SekPixelSize)) + i


x / y = Aktuelle kachel
Self.x / Self.y = Aktueller Sektor (Durchnummeriert von -2,1mrd bis +2,1mrd)
tileSize = Konstante (momentan 8)
SekPixelSize = Konstante (momentan tileSize * 64)

Wenn ich die Vertexdaten nur mit y bzw x * tilesize in das VBO eintrage, und die verschiebung per glTranslated() vornehme, wird es anscheinend richtig dargestellt.
Kann mir das vielleicht jemand erklären? Smile

Nun gut, ich zerpflücke meinen Code mal in ein paar (evtl) relevanten teile:

BlitzMax: [AUSKLAPPEN]
'Konstanten:
Const ResX:Int = 1024, ResY:Int = 768 'Auflösung
Const TileSize:Int = 8 'Größe einer kachel
Const SekTileCnt:Int = 64 'Anzahl kacheln Pro spalte/reihe im Sektor
Const SekPixelSize:Int = SekTilecnt * TileSize 'Größe einer Sektorspalte/reihe in pseudo-pixeln
Const textureCnt:Int = 1 'noch nicht genutzt

'[...] Weitere globals hier, unrelevant.

'Init von Ogl:
GLGraphics(ResX, ResY, 0,60)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

glOrtho(0, ResX, ResY, 0, 0, 128) ' Oben = ResY, da ich ein Koordinatensystem von Oben links nach unten rechts gewohnt bin!

'[...]

'Forschleifen, die das erstellen der VBO's im TSektor objekt aufrufen - hier der VBO Code:

Method FillVBO:Int()

'Der code wurde aus der alten drawroutine umfunktioniert. minX etc sind noch fragmente, die das zeichnen der Kacheln begrenzt haben (nur sichtbares wurde gezeichnet!)
Local minX:Int = 0 'deshalb Hardcoded - wurden hier vorher ausgerechnet.
Local maxX:Int = 63
Local minY:Int = 0
Local maxY:Int = 63

glGenBuffersARB(1, Varptr(Self.vbo[0])) 'neuen Buffer anlegen
glBindBufferARB(GL_ARRAY_BUFFER_ARB, Self.vbo[0]) 'buffer binden um ihn zu nutzen.

'Größe der vertexdaten:
Local iSize:Int = 64 * 64 * 4 * 5
'Größe der farbdaten:
Local colSize:Int = 64 * 64 * 4 * 3

'64*64 kacheln, je 4 vertex, U V R G B X Y Z

'Vertex-array (re)intialisieren:
Self.vboArr = New Float[iSize + colSize]
Local color:Float = 0 'Vorreservieren der Variable, um nicht 64*64 mal eine Local zu intialisieren (meine fps-geilheit eben *g*)
Local xpos:Float = 0, ypos:Float = 0 'Vorreservieren der positions-Variablen

Local x:Int = 0 'Vorinitialsieren der For-zähler
Local y:Int = 0

'Y reihe durchgehen
For y = minY To maxY
'Ypos errechnen
ypos = (y * (TileSize))

'X reihe durchgehen
For x = minX To maxX
'xpos errechnen.
xpos = (x * (TileSize))


color = 1.0 'erstmal statisch festgelegt.

'Das eintragen der Vertexdaten. Die Y koordinate wird testhalber errechnet (von 0.0 bis 0.25 bzw von 0.25 bis 0.5!)
'Reihenfolge der Daten:
'X koordinate Textur (U)
'Y koordinate Textur (V)
'R wert des Vertex
'G wert des Vertex
'B wert des Vertex
'X position des Vertex
'Y Position des Vertex
'Z position des Vertex - immer 0!

'vertex1!
vboArr[vboSize + 0] = 0.0
vboArr[vboSize + 1] =.25 * ((Self.y + 2) Mod 2)
vboArr[vboSize + 2] = color
vboArr[vboSize + 3] = color
vboArr[vboSize + 4] = color
vboArr[vboSize + 5] = xpos
vboArr[vboSize + 6] = ypos
vboArr[vboSize + 7] = 0.0
vboSize:+8

'vertex2!
vboArr[vboSize + 0] = 1.0
vboArr[vboSize + 1] =.25 * ((Self.y + 2) Mod 2)
vboArr[vboSize + 2] = color
vboArr[vboSize + 3] = color
vboArr[vboSize + 4] = color
vboArr[vboSize + 5] = xpos + (TileSize)
vboArr[vboSize + 6] = ypos
vboArr[vboSize + 7] = 0.0

vboSize:+8

'vertex3!
vboArr[vboSize + 0] = 1
vboArr[vboSize + 1] =.25 * ((Self.y + 2) Mod 2) +.25
vboArr[vboSize + 2] = color
vboArr[vboSize + 3] = color
vboArr[vboSize + 4] = color
vboArr[vboSize + 5] = xpos + (TileSize)
vboArr[vboSize + 6] = ypos + (TileSize)
vboArr[vboSize + 7] = 0.0

vboSize:+8

'vertex4!
vboArr[vboSize + 0] = 0.0
vboArr[vboSize + 1] =.25 * ((Self.y + 2) Mod 2) +.25
vboArr[vboSize + 2] = color
vboArr[vboSize + 3] = color
vboArr[vboSize + 4] = color
vboArr[vboSize + 5] = xpos
vboArr[vboSize + 6] = ypos + (TileSize)
vboArr[vboSize + 7] = 0.0

vboSize:+8

Next 'Ende forschleife für X
Next 'Ende forschleife für Y

'Testhalber den Array auf seine tatsächliche größe Slicen (wohl noch ein fragment von vorgestern? ^^)
Self.vboArr = Self.vboArr[..vboSize]

'Bufferdaten eintragen, glaube ich.
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vboSize * 4, Varptr(Self.vboArr[0]), GL_STATIC_DRAW_ARB) ;

End Method

'[...] Nun beginnt die hauptschleife. (-> While Not KeyHit(KEY_ESCAPE) And Not AppTerminate() )

'Darin der aufruf des Zeichnens:
glPushMatrix() 'Matrix Sichern
glEnableClientState(GL_VERTEX_ARRAY) '?? chrm. Ich muss das machen, ich weiß nur nochnicht wieso genau :D

'Anmkerung: Ich habe immer 5x5 sektoren geladen. Der rest soll später von der platte nachgeladen werden und der ActSek array neu gebaut werden!
For Local x:Int = 0 Until 5

'Verschieben - der Versatz, der eigentlich mit in den Vertexdaten rein sollte.
glTranslated(SekPixelSize, 0, 0)
For Local y:Int = 0 Until 5
'Ein weiteres verschieben
glTranslated(0, SekPixelSize, 0)
ActSek[x,y].Draw() 'Aufruf der DrawMethode
Next
glTranslated(0, -5 * SekPixelSize, 0) 'Zurückschieben.
Next
glDisableClientState(GL_VERTEX_ARRAY) 'wieder deaktivieren
glPopMatrix() 'Matrix zum ausgang zurücksetzen.


'[...]

'Draw methode: (TSektor objekt!)
Method Draw()

'den sektoreigenen Buffer binden
glBindBufferARB(GL_ARRAY_BUFFER_ARB, Self.vbo[0]) ;
'OpenGL mitteilen, wie mein Array aufgebaut ist
glInterleavedArrays(GL_T2F_C3F_V3F, 0, Null)

'Elemente zeichnen. ps: Quads wird ausgetauscht gegen GL_Triangle, sobald ich ein Indexobjekt erstellen konnte.
glDrawArrays(GL_QUADS, 0, 64 * 64 * 4) 'Start bei 0, 64*64*4 vertices sind zu zeichnen.

End Method

'[...]
Flip 0
'Ende der hauptschleife


So im groben ist mein programm aufgebaut.

Ich hoffe, ich habe das VBO endlich richtig erstellt+gezeichnet.
Wie es klang, habe ich nicht grade die schnellste Methode gewählt, aber sie war, meines erachtens, erstmal die einfachste.
Sobald ich das ganze Thema besser verstanden und verinnerlicht habe, werde ich anfangen, mit einem IBO zu arbeiten, um u.a. den Reservierten speicher in Grafikkarten-ram zu vermindern.

Was ich noch nicht ganz verstanden habe, ist der 2te parameter aus
BlitzMax: [AUSKLAPPEN]
glInterleavedArrays(GL_T2F_C3F_V3F, 0, Null)


Sowohl 0 wie auch 8*4 scheinen richtige ergebnisse zu liefern.
Laut google etc sollte ich da den Byte-abstand zwischen 2 Vertex-datenbündeln eintragen. DH 8*4 wäre korrekt (8 daten zu je 4 byte)
Aber trotzdem liefer 0 das richtige ergebnis - jede kachel wird korrekt dargestellt.

Des weiteren verstehe ich nicht, was es für einen unterschied macht, ob ich im VBO nun direkt meine 'Totalen' koordinaten angaben eintrage, oder ob ich die matrix mit glTranslated() manipuliere, bevor ich das VBO zeichne.


Ich hoffe, ihr könnt mir eventuelle fehler aufzeigen und mir ein paar ratschläge mitgeben. Ich glaube, es wird an der Zeit, mich intensiver mit Matrizen zu befassne - bis jetzt konnte ich immer damit arbeiten und habe sie auch korrekt misshandeln können, aber verstehen tu ich das ganze noch nicht *g*

PS: Ist es eigentlich immer so, das man sich Tagelang den kopf zerbricht, kein ergebniss erzielt und dann, wenn endlich seinen Scham überwunden hat und im Forum postet, seine ersten eigenen ergebnisse erzielt? Das passiert mir immer wieder und es ist einfach peinlich :<


Liebe grüße, Phillipk

Noobody

BeitragDo, Jul 14, 2011 11:46
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzMax: [AUSKLAPPEN]
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

glOrtho(0, ResX, ResY, 0, 0, 128)

Ooooh, das ist ganz übel. Projektionsmatrizen nur nach GL_PROJECTION.

In deinem Fall funktioniert es sogar noch, da du immer schön artig die Matrix mit Pop- bzw. PushMatrix auf den Stack rettest, bevor du sie bearbeitest. Trotzdem aber ist es keine gute Programmierpraxis und kann in vielen Fällen zu unerwarteten Resultaten führen.

Ansonsten scheint der Code korrekt zu sein (abgesehen von glInterleavedArrays und GL_QUADS, die man mittlerweile nicht mehr verwenden sollte, aber das weisst du ja vermutlich schon). Dass die Verschiebung im VBO nicht funktionieren sollte, macht nicht wirklich Sinn - wenn die Positionen der Tiles schon korrekt übernommen werden, warum dann nicht die Position der Sektoren? Probier es doch nochmal mit der Projektionsmatrix am korrekten Ort und stelle sicher, dass du die glTranslate-Aufrufe beim Testen auskommentierst.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

PhillipK

BeitragDo, Jul 14, 2011 12:00
Antworten mit Zitat
Benutzer-Profile anzeigen
ÖÖöööhm..

Das kommt wohl davon, wenn man sich in ein Thema durch Tutorials etc reinfuttert.
Das matrixmodeding zb habe ich noch nicht kapiert - das erste OGL intialisieren hab ich 1zu1 von einer bekannten übernommen (Die es wohl auch falsch macht *g*)

Der VBO-Teil des Codes ist aus meiner alten drawfunktion entstanden.
Statt einem glBegin(GL_QUADS); glVertex2f() [...]; glEnd() batzen habe ich stattdessen die variablen in die Array-positionen geschrieben.
Vorher hats geklappt, deswegen kam ich auch nicht darauf, das die VBO's einfach falsch dargestellt werden.
Ich werde gleich mal den änderungsvorschlag übernehmen.
Danach schraube ich mein VBO-Erstellen wieder um, das ermöglicht mir, die map mittig auf punkt 0,0 zu halten (und das ohne gltranslated! Smile )

Allerding werd ich erst in etwa ner stunde wieder Programmieren, meine freundin hat vorrang *g*

----

Edit 14.07.2011 - 12:45:

Auja, nun klappt alles!
Hatte allerdings auchnoch ein Satzzeichen vertauscht. DAS war der fehler.
Statt die sektorposition zu addieren, habe ich sie mit der kachelposition multipliziert. Mein wahn, das ich mit dem vbo nicht klarkomme, hat mich wohl blind gemacht.

Nundenn, dann starte ich gleich mal mit der nächsten Frage, die hier wohl auch zu passt.
GL_QUADS sollte ich in soweit vermeiden, da Grafikkarten (meist?) nur mit Triangles arbeiten, und meine GL_QUADS zu 2 GL_TRIANGLE umformen. Das braucht rechenzeit (und ist bei 64*64*5*5 Quads evtl sogar eine verbesserung wert!).
Schritt eins wird sein, das ich ein IBO - Index Buffer Object - erstellen möchte.
Gestern habe ich noch gerätselt, was da wohl reingehört, mittlerweile habe ich eine vermutung.
Statt das ich OpenGL mitteile, welchen array ich gedrawt haben möchte & wieviel davon, nehme ich einen weiteren array- ein array mit indexzahlen. Gell? Smile

Sowie ich es intepretiert habe:

VBO - Vertixes mit ihren positionen.
IBO - Für die 'faces' - index 0 = Triangle 1 vertex1 Index in VBO., index 1 = Triangle 1 vertex2 Index in Vbo, index2 = Triangle1 vertex3 Index in vbo.

So halte ich für jedes Quad 4 vertixes, worauf ich insg. 2 Triangles verlinke.
Weiter optimiert kann ich in meinem fall wohl ein Raster erstellen, dh statt jeder Kachel 4 vertixes zuzuordnen, nehme ich einfach die Vertixes der anliegenden kacheln.

Ich hoffe ich habe das ganze richtig erklärt. Bekannt kommt mir das system minib3d vor.
Dort habe ich mich bereits einmal mit Vertexmanipulation befasst (um große mengen Von items bei wenig Surface's zu ermöglichen, habe ich dort direkt die Tri's / Vert's bearbeitet. Der Tri's array dort scheint mir ziemlich identisch mit einem IBO zu sein, der Vert's array hingegen mit einem VBO)

Jetzt ist nur die frage, was ich mit den Color und Texturdaten anfange ^^

Ich hol mir mal ne kippe und fülle dann ein IBO mit den entsprechenden daten und versuche gleichermaßen, die Vertexzahl zu vermindern.
(ich nutze im moment 64*64*4 vertixes pro Sektor, grob gepeilt brauch ich nach einer optimierung in raster-richtung nurnoch (64*64)+64+64 Vertixes pro sektor, ein 'neues' pro kachel und eine weitere reihe rechts / unten.)
 

PhillipK

BeitragDo, Jul 14, 2011 19:00
Antworten mit Zitat
Benutzer-Profile anzeigen
ich hänge fest.

Ich habe versucht, meine 3 daten zu trennen, um sie flexibler nutzen zu können.

Hierraus ist nichtmehr nur ein Self.Vbo buffer entstanden, sondern auch Texture Buffer (typ T2F -> U,V,U,V...) und ein ColorBuffer (type C3F -> R,G,B,R,G,B...).

Mein VBO hält nun nurnoch die vertexdaten im stil V3F -> x,y,z,x,y,z...

Allerdings gibts nun beim zeichnen probleme.

Ersteinmal der Zeichenaufruf:

BlitzMax: [AUSKLAPPEN]
		glPushMatrix()
glEnableClientState(GL_VERTEX_ARRAY) ;
glEnableClientState(GL_COLOR_ARRAY) ;
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
For Local u:Int = 0 Until 5

glTranslated(SekPixelSize, 0, 0)
For Local r:Int = 0 Until 5
glTranslated(0, SekPixelSize, 0)


ActSek[u, r].Draw()

Next
glTranslated(0, -5 * SekPixelSize, 0)
Next
glDisableClientState((GL_TEXTURE_COORD_ARRAY))
glDisableClientState(GL_COLOR_ARRAY) ;
glDisableClientState(GL_VERTEX_ARRAY)

glPopMatrix()


Hab brav und in ordentlicher reihenfolge die ClientStates wieder deaktiviert.

Dann kommts zum Draw:
BlitzMax: [AUSKLAPPEN]
	Method Draw()

glBindBufferARB(GL_ARRAY_BUFFER_ARB, Self.vbo[0]) ;
glVertexPointer(3, GL_FLOAT, 0, Null)

glBindBufferARB(GL_COLOR_ARRAY_BUFFER_BINDING_ARB, Self.col[0])
glColorPointer(3, GL_FLOAT, 0, Null)

glBindBufferARB(GL_TEXTURE_BUFFER_ARB, Self.tex[0])
glTexCoordPointer(2, GL_FLOAT, 0, Null))

glDrawElements(GL_TRIANGLES, SekTileCnt * SekTileCnt * 6, GL_UNSIGNED_INT, Varptr(Self.iboArr[0])) ;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)
End Method


Was ich hier nicht ganz verstehe:

Die NULL bei den Pointer-aufrufen, dort sollte eigentlich ein Pointer zum ersten element meines array stehen, nicht war? (Siehe: VarPtr(Self.iboArr[0]) - setze ich dort jeweiles mein VBOArr, ColArr und TexArr - pointer ein, zeichnet er mir garnichts.
Setze ich dort null rein, so gibts irgendwelche Braunen flächen über den ganzen bildschirm.
einmal zwischendrin habe ich auch ein grünes tri's gesehen.
Vllt isses zufall, aber meine textur enthält wirklich Braun und Grüne (testweise ein Erde-mit-gras-tile)

Des weiteren war ich mir absolut unsicher, wie ich die Tex und Col arrays zu handhaben habe.
Diese sollten in der Theorie relativ flexibel ausgetauscht werden, grade der Tex array.
Sollte ich diese auch zur grafikkarte hochladen, wie mein VBO? Oder grade nicht?
Kann ich das ganze nur nutzen, wenn ich sie nicht hochlade?

Zu guter letzt noch das binden der Array-sammlungen:

BlitzMax: [AUSKLAPPEN]

glGenBuffersARB(1, Varptr(Self.vbo[0])) 'neuen Buffer anlegen
glGenBuffersARB(1, Varptr(Self.ibo[0])) 'index buffer anlegen
glGenBuffersARB(1, Varptr(Self.tex[0])) 'neuen textur buffer anlegen.
glGenBuffersARB(1, Varptr(Self.col[0]))

'[....] Füllen der arrays etc. Wie gehabt, nur getrennt auf 4 arrays!

glBindBufferARB(GL_ARRAY_BUFFER_ARB, Self.vbo[0]) 'buffer binden um ihn zu nutzen.
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vboSize * 4, Varptr(Self.vboArr[0]), GL_STATIC_DRAW_ARB) ;

glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, Self.ibo[0])
glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, SizeOf(Self.iboArr), Varptr(Self.iboArr[0]), GL_STATIC_DRAW_ARB) ;

glBindBufferARB(GL_TEXTURE_BUFFER_ARB, Self.tex[0])
glBufferData(GL_TEXTURE_BUFFER_ARB, SizeOf(Self.texArr), Varptr(Self.texArr[0]), GL_STATIC_DRAW_ARB)

glBindBufferARB(GL_COLOR_ARRAY_BUFFER_BINDING_ARB, Self.col[0])
glBufferData(GL_COLOR_ARRAY_BUFFER_BINDING_ARB, SizeOf(Self.colArr), Varptr(Self.colArr[0]), GL_STATIC_DRAW_ARB)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)


GL_TEXTURE_BUFFER_ARB habe ich mir aus irgendeinen Tutorial geklaubt.
Aber es scheint nirgendwo ein Tutorial zu geben, wo der color-array seperat gehandhabt wird.

Jedes tutorial nutzt anscheinend nur VBO's im stil C3_V3 bzw vllt nocht textur dabei.
Das ganze wird mit glInterleaved array vorbereitet und fertig.
Darum habe ich mit GL_COLOR_ARRAY_BUFFER_BINDING_ARB einfach mal zusammengereimt, von der auswahl war es das logischste.

Wäre nett, wenn mir hier jemand unter die Arme greifen würde, ich verzweifle nämlich grade ein wenig Cool

Noobody

BeitragDo, Jul 14, 2011 22:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Verschiedene Daten aus mehreren VBOs beim Zeichnen zu benutzen ist so nicht möglich. GL_TEXTURE_BUFFER hat überhaupt nichts mit Texturkoordinaten in einem VBO zu tun, sondern mit einer eindimensionalen Textur, die vom Speichermanagement ähnlich flexibel wie ein VBO zu handhaben ist (wird z.B. für transform feedback in Partikelsystemen verwendet) und benötigt ausserdem Shader Model 4.0. GL_COLOR_ARRAY_BUFFER_BINDING ist... keine Ahnung Razz Das ist in keiner Dokumentation gross erwähnt, wo hast du das her? Man kann zumindest abschätzen, dass es nichts mit glBindBuffer zu tun hat - Konstanten mit _BINDING am Ende werden eigentlich nur bei glGet verwendet.

Und sogar wenn es ginge, würde dir das nichts nützen - du kannst zwar die Koordinaten angrenzender Vertices für mehrere Tiles benutzen, aber die Texturkoordinaten angrenzender Tiles sind mit grosser Sicherheit verschieden. D.h. um deinen Speicherspar-Plan umzusetzen, müsstest du die Vertexkoordinaten mit einem anderen Index ansteuern als die Texturkoordinaten, was nun mal nicht geht.

Daher: Steck alle Daten in einen VBO, das ist einfacher. AAA Titel arbeiten mit einem Budget von 300'000 Polygonen und ungefähr gleich viel Vertices, da musst du dir um den Speicherverbrauch wegen ein paar 10'000 Vertices für eine Tilemap überhaupt keine Sorgen machen.

Zum letzen Parameter von gl**Pointer: Wenn du VBOs benutzt, musst du dort nicht den Zeiger auf dein VBO-Array angeben (das liegt im Hauptspeicher und bringt der GPU nichts), sondern den Offset im VBO selbst. In deinem Fall hast du ja U, V, R, G, B, X, Y, Z für den Vertex vorliegen, das heisst, Texturkoordinaten beginnen bei Offset 0, Vertexfarben bei Offset 8 (2*4 Bytes) und Position bei Offset 20 (2*4 + 3*4 Bytes). Das einzige Problem hier ist, dass die Funktion einen Pointer nimmt und nicht einen Integer, da die Funktion auch für einen anderen Zweck verwendet wird, bei dem tatsächlich ein Zeiger in den Hauptspeicher benötigt wird. Da du in BMax nicht direkt einen Integer in einen Zeiger verwandeln kannst, habe ich immer diesen Trick hier verwendet: BlitzMax: [AUSKLAPPEN]
Local NullPointer:Byte Ptr = Null

glBindBufferARB(GL_ARRAY_BUFFER_ARB, Self.vbo[0])
glVertexPointer(3, GL_FLOAT, 0, NullPointer + 20) 'Oder welchen Offset auch immer du verwenden möchtest


Was mir auch noch auffällt: Du verwendest zwar einen VBO für die Indizes, zeichnest aber effektiv mit dem BMax-Array, das im Hauptspeicher liegt (was sehr langsam ist). Binde daher zuerst den Index-Buffer, bevor du glDrawElements verwendest: BlitzMax: [AUSKLAPPEN]
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, Self.IBO[0])
glDrawElements(GL_TRIANGLES, SekTileCnt * SekTileCnt * 6, GL_UNSIGNED_INT, Null)


Und noch ein letzter Tipp: 32-Bit Indizes werden nicht unbedingt von allen Grafikkarten unterstützt. Benutze daher 16-Bit Indizes (GL_UNSIGNED_SHORT) wo möglich.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

PhillipK

BeitragFr, Jul 15, 2011 4:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:

Und sogar wenn es ginge, würde dir das nichts nützen - du kannst zwar die Koordinaten angrenzender Vertices für mehrere Tiles benutzen, aber die Texturkoordinaten angrenzender Tiles sind mit grosser Sicherheit verschieden. D.h. um deinen Speicherspar-Plan umzusetzen, müsstest du die Vertexkoordinaten mit einem anderen Index ansteuern als die Texturkoordinaten, was nun mal nicht geht.


Jaa das ist mir nach meinem ersten überlegungswahn auch eingefallen Smile Mehrere UV's pro vertex sind maximal per multitextur (so wie es sich liest) realisiertbar.

GL_TEXTURE_BUFFER_ARB ist entweder in meinem Wahn dareingerutscht, oder aus einem Tutorial entstanden.

Ich habe das ganze etwas einfacher vor und nun den ganzen abend rumgespielt, leider klappt es immernochnicht.
Ich möchte lediglich jedem vertex pro Sektor eigene Werte zuteilen (auf jedenfall UV, evtl aber auch Color).
Eine bekannte nutzt das ganze ähnlich, deswegen dachte ich, ich kanns einfach auf VBO's übertragen.

Sie nutzt Einen Colorarray, einen UVArray und einen Vertexarray, und zeichnet das ganze mit DrawArray, wenn ich mich nicht irre. Das ganze wird mit glDrawArray() oder so gezeichnet :3 Klappt 100% - hab mich gestern noch davon überzeugt.
Der überlegung nach, möchte ich nicht viel mehr anders machen: Ich möchte das ganze lediglich durch ein VBO und ein IBO erweitern, die daten liegen im Grafikkarten RAM vor.
Die textur und Colordaten sollen aus einem eigenen Array stammen, die IBO und VBO daten sollen im g-ram vorliegen. Nutzung soll gleichermaßen bleiben:
VERTEX1 - xyz - uv - RGB
VERTEX2 - xyz - uv - RGB

BlitzMax: [AUSKLAPPEN]
glVertexPointer([b]3[/b], GL_FLOAT, 0, Null) 'Es liegt der reihe nach vor: v1X v1Y v1Z v2X v2Y v2Z
glColorPointer( [b]3[/b], GL_FLOAT, 0, Null) 'Es liegt der reihe nach vor: v1R v1G v1B v2R v2G v2B
glTexCoordPointer([b]2[/b], GL_FLOAT, 0, Null) 'es liegt der reihe nach vor: v1U v1V v2U v2V


-------

Das ich das ibo aus dem RAM nutze, ist mir auch aufgefallen, das hatte ich bereits gefixt.
Das ganze habe ich gute 3x umgewälzt. Mittlerweile ist mir aufgefallen, das vertices zwar noch gezeichnet werden, allerdings haben sie alle als uv koordinate eine 0,0!

------
Für den trick mit dem pointer bin ich dankbar Smile Wenn ich das ganze wieder zum laufen kriege, wird das bei weiteren spielereien helfen.

Zitat:
Und noch ein letzter Tipp: 32-Bit Indizes werden nicht unbedingt von allen Grafikkarten unterstützt. Benutze daher 16-Bit Indizes (GL_UNSIGNED_SHORT) wo möglich.

Gut, das wusste ich nicht. Im moment sollte das kein problem sein, da ich 64*64*3*2 Tri's besitze. Dh ich kann fast 3mal soviele Tris halten, wenn gewollt Smile


Nunjut, ich werde nochmal schauen, das ich zumindest den Texturenbuffer hinkriege. Wenn alle stricke reißen [kann ich mich nichteinmal mehr aufhängen!] muss ich doch wieder auf mehrere VBO umsteigen Sad

Aber dennoch, ein Dickes dankeschön, Noobody, das du mir unter die arme greifst Smile Ich bin schon ganz verzweifelt^^

Liebe grüße, Phillip Smile

Edit 15.07.2011 - 05:24:

Okay fürs erste gebe ichs auf.
Da ist mir ein streßtest, wie lange es dauert, ein vbo alle 2 frames zu 'updaten' lieber Sad

Ich werde mein array erstellen ersteinmal wieder umstellen und mir ein VBO im ganzen nehmen. :/

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group