PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Vertex Structure...


che g
2003-10-09, 19:59:04
...wie aufbauen?


struct VERTEX
{
float x,y,z;
float u,v;
};

struct VERTEX1
{
float Coord[3];
float TexCoord[2];
};


Macht das überhaupt einen Unterschied?

Bei einem Array sind die einzelnen Elemente im Speicher ja garantiert hintereinander, kann es sein dass die 3 einzelnen float an verschiedenen (Speicher)Positionen angelegt werden?

Dann wäre nämlich die 2. Variante besser, weil sparsamer mit Adresssprüngen.

Mfg

Gast
2003-10-09, 20:22:47
Original geschrieben von che g

Macht das überhaupt einen Unterschied?

Bei einem Array sind die einzelnen Elemente im Speicher ja garantiert hintereinander, kann es sein dass die 3 einzelnen float an verschiedenen (Speicher)Positionen angelegt werden?

Dann wäre nämlich die 2. Variante besser, weil sparsamer mit Adresssprüngen.

Mfg

Also der Compiler findet das ganz lieb, wenn du das ganze in 4er Blöcke anordnest :)
Dann kann er auch selber besser für SSE optimieren (was du ja scheinbar nicht selber machen willst ;) )
Bei deinen Beispielen hat man aber nicht wirklich einen Unterschied. Die erste Version lässt sich aber leichter handhaben find ich.
Ich würd noch überprüfen, ob du die Daten auch wirklich meistens zusammen brauchst. Ansonsten trenn das in 2 structs damit sie auch im Speicher getrennt sind und du nicht den Cache mit unnützen Informationen zumüllst :)

Xmas
2003-10-10, 02:36:02
Original geschrieben von che g
...wie aufbauen?


struct VERTEX
{
float x,y,z;
float u,v;
};

struct VERTEX1
{
float Coord[3];
float TexCoord[2];
};


Macht das überhaupt einen Unterschied?

Bei einem Array sind die einzelnen Elemente im Speicher ja garantiert hintereinander, kann es sein dass die 3 einzelnen float an verschiedenen (Speicher)Positionen angelegt werden?

Dann wäre nämlich die 2. Variante besser, weil sparsamer mit Adresssprüngen.

Mfg

Wieso nicht folgendes?

struct VERTEX
{
union
{
float coord[3];
struct { float x, y, z; };
};
union
{
float texCoord[2];
struct { float u, v; };
};
};

Dann kannst du auf beide Arten auf die Koordinaten zugreifen. Ansonsten solltest du auch die Anmerkungen des Gastes beachten.

DocEW
2003-10-10, 02:49:05
Original geschrieben von Gast
Dann kann er auch selber besser für SSE optimieren (was du ja scheinbar nicht selber machen willst ;) )

Wußte gar nicht, daß Java SSE benutzt... wow. Aber generell erst seit J2SE 1.4.2, wie's aussieht:

http://developer.java.sun.com/developer/community/chat/JavaLive/2003/jl0429.html

MeLLe
2003-10-10, 09:56:40
Original geschrieben von DocEW
Wußte gar nicht, daß Java SSE benutzt... wow. Aber generell erst seit J2SE 1.4.2, wie's aussieht:
Gings hier um Java? ???

DocEW
2003-10-10, 11:49:20
Original geschrieben von MeLLe
Gings hier um Java? ???
Uupss... hatte so viele Threads offen, in denen es um Java ging, daß ich das irgendwie verpeilt habe... naja, um die Uhrzeit... =)

che g
2003-10-11, 22:20:44
Dankeschön:)

4er Blöcke, da brauch ich dann aber Füllbytes. So eine SSE Optimierungen wär schon was feines...:)

MfG

Gast
2003-10-14, 14:50:53
Du brauchst nicht unbedingt Füllbytes
Dafür gibts eine Hybridstruktur zwischen SoA und AoS :)


typedef struct
{
float x[4];
float y[4];
float z[4];
} VectorGroup;

VectorGroup VERTEX[numofvertexgroups];

Theoretisch solltest du dabei, wenn du noch nen zusätzlichen 4er-Block verbauen kannst, nochmal an Performance gewinnen. Unnötig auffüllen lohnt aber nicht. Das war zumindest bei mir bis jetzt immer langsamer bei Tests ;)

micki
2003-10-14, 15:29:08
mein compiler mag indices nicht so gerne wie einzelne variablen, der c++ code disassembliert sah optimaler aus und gebenched waren auch ein paar % mehr drinne mit einzelnen variablen.


gruesse
micki

Gast
2003-10-14, 16:27:09
Kommt erstens auf den Compiler an und zweitens was man später mit macht.
Wenn ich einfach einen Block auf einmal in ein SSE Register reinschieben kann, ist das schon vom Programmieren her angenehmer ;)
Ausserdem bräuchtest du bei einfachen Variablen noch 4 Byte zum Auffüllen, weils sonst mit dem 16 Byte-Alignment nicht hinkommt :/
Man kann zwar auch unaligned Data verwenden. Allerdings wirds dann merklich langsamer.

Aber das spielt jetzt wirklich nur mit SSE eine Rolle ;)

che g
2003-10-15, 17:51:35
Weils gerade passt ein paar Fragen zu möglichst effizientem Geometrietransfer:

Die beste Möglichkeit sind wohl Triangle Strips. (oder Fans, die sind aber nicht so universell einzusetzen)
Bei meiner 512x512 Heightmap habe ich nur geringe Unterschiede zwischen Immediate Mode und Vertex Arrays, was wahrscheinlich daran liegt dass bei beiden Methoden 512 RenderCalls nötig sind: jeweils einer für eine "Zeile" Terrain. Gibt es hier vielleicht eine Methode wie man mehrere "Zeilen" zu einem einzigen Strip zusammenfassen kann? (Dazu gabs schonmal einen Thread von mir IIRC scheiterte es an der Vertexreihenfolge CW vs. CCW)

Bei Immediate Mode und Vertex Arrays liegen die Daten ja im Hauptspeicher, bei VBOs AFAIK direkt im Grafikkarten-RAM, das könnte noch Geschwindigkeit bringen. Allerdings hat man gerade auf der Graka nicht unbegrenzt Speicher zur Verfügung: 512*512 =262144 Vertices * 20 Bytes (je 5 floats/Vertex, 3xKoordiante + 2xTexturkoordinate) = 5.242.880 Bytes = 5,2 MB immerhin. Nicht zu vergessen der Speicher für die Indexliste...

Was tun?

MfG

ScottManDeath
2003-10-15, 18:23:26
Hi

japps, das geht. dazu musst du wenn du mit einem strip am ende bist ein degeneriertes dreieck (mit fläche null) einfügen und dann den strip in der anderen richtung weiterführen.....

ich hatte das auch mal gemacht, allerdings mit indizierten strips, zum brainstorming hab ich mir auf papier ein einfaches grid aufgemalt und dann die indizes dazu, danach dann den algorithmus für die indizes abgeleitet...

gerendert wird das ganze dann mit glDrawElements

alternativ kannst du auch die vertexdaten und die indexdaten in jeweils getrennte VBO' stopfen.

hat bei mir (mit alten treibern) kaum unterschiede zwischen vbo und va gegeben...... muss ich mal mit aktuellen treibern testen

wenn du willst kann ich dir auch den rest des codes schicken (IM, VA, VBO)


void height_field_renderer_std::init_indices()
{

size_t w = m_height_field->get_width();
size_t h = m_height_field->get_height();
m_indices = new GLuint [(w-1)*2* h];

size_t u;
size_t v;
size_t i=0;


for(u=0; u < w -1 ; u++)
{
size_t n = 0;
v = u;
while ( n < 2*h)
{
m_indices[i++] = v++;
m_indices[i++] = v++;
v+=(w-2);
n+=2;


}

}

{
size_t all_size = 1+ (w-1)*(2*h-1);
m_all_indices = new GLuint[all_size];

size_t index = 1;
size_t count = 1;
size_t cur = 1;
bool up = true;
int n = 0;

m_all_indices[0]=0;

while ( count < all_size)
if(up)
{
if(n < int(2*(h-1)))
{

m_all_indices[index++] = cur;
cur+= (w-1);
m_all_indices[index++] = cur++;
n+=2;
count+=2;
}
else
{
m_all_indices[index++] = cur++;
count++;
up=false;
n=0;
}

}
else
{
if ( n < int(2*(h-1)))
{
m_all_indices[index++] = cur;
cur-= (w+1);
m_all_indices[index++]= cur++;
n+=2;
count+=2;
}
else
{
m_all_indices[index++] = cur++;
count++;
up=true;
n=0;
}
}






}




void height_field_renderer_va::render() const
{

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(3, GL_FLOAT,0,m_height_field->get_positions());
glNormalPointer(GL_FLOAT,0,m_height_field->get_normals());
glTexCoordPointer(2,GL_FLOAT,0,m_height_field->get_texcoords());




size_t max = 1+ (m_height_field->get_width()-1)*(2*m_height_field->get_height()-1);

glDrawElements(GL_TRIANGLE_STRIP,max,GL_UNSIGNED_INT,m_all_indices);


glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);



}

liquid
2003-10-15, 18:24:58
Man kann afaik die Orientierung (CW und CCW) durch Einsatz von degenerierten Dreiecken "umdrehen". Dazu dupliziert man einfach die passenden Vertices am Ende der Strips.
Ich hab das mal auf Papier "implementiert" gehabt und auch in meine Engine eingebaut, aber der Source ist ja immer noch futsch (Recovery Thread im Windows Bereich) und das Papierchen finde ich auch nicht auf die schnelle. Am besten mal selber mit Bleistift und Ratzefummel austüfteln.

cya
liquid

EDIT: Scott hats :D

che g
2003-10-16, 12:17:01
Interessant...

Wieviel Geschwindigkeit bringt das ein sagen wir 512x512 Heightfield mit degenerierten Strips zu rendern (1 RenderCall) gegenüber der normalen Methode(512 RenderCalls). Habt ihr da Erfahrungswerte? Lohnt sich der Aufwand?

MfG

micki
2003-10-16, 13:21:19
bist du bei ca 4-6fps mit deinem 512*512 heightfield?

gruesse
micki

Xmas
2003-10-17, 01:19:43
Es gibt übrigens effizientere Methoden als die komplette Breite des Heightfields erst in eine, dann in die andere Richtung immer abwechselnd zu durchlaufen. Dabei hat man nämlich eine ziemlich lausige Vertex-Cache Hit-Rate.

ScottManDeath
2003-10-17, 01:54:26
Original geschrieben von Xmas
Es gibt übrigens effizientere Methoden als die komplette Breite des Heightfields erst in eine, dann in die andere Richtung immer abwechselnd zu durchlaufen. Dabei hat man nämlich eine ziemlich lausige Vertex-Cache Hit-Rate.

ja, IRC hat Demirug das mal hier irgendwo erwähnt...... das kostet dann aber noch mehr Kopfschmerzen beim algorithmusherleiten ;)

lief wohl auf ein Mäandermuster hinaus....

liquid
2003-10-17, 16:31:25
Da melde ich mich gleich mal, da mich sowas auch interessieren würde. Irgendwelche Links zur Hand??

cya
liquid