Die Variante mit vec4 geht, aber die mit vec3 kommen falsche Parameter beim Shader an.
Code:
//layout (std140) uniform Material {
// vec3 Mambient; // Umgebungslicht
// vec3 Mdiffuse; // Farbe
// vec3 Mspecular; // Spiegelnd
// float Mshininess; // Glanz
//};
//
layout (std140)uniform Material {
vec4 Mambient;// Umgebungslicht
vec4 Mdiffuse;// Farbe
vec4 Mspecular;// Spiegelnd
float Mshininess;// Glanz
};
Lazarus Seitig habe ich es auch angepasst.
Code:
type
TMaterial =record
ambient,
diffuse,
specular: TVector4f;// Auf TVector3f geändert.
shininess: GLfloat;
end;
Das einzige was mit vec3 beim shader richtig ankommt, ist ambient. Ich habe es ach mit "packed record" probiert, bringt auch nichts, Was habe ich übersehen ?
Registriert: So Aug 08, 2010 08:37 Beiträge: 460
Programmiersprache: C / C++ / Lua
Lies dir Mal in der glsl spec durch sie alignment bei ubos funktioniert.
TL;Dr: die Dinger sind vec4 alignt. Folglich musst du entweder ein Union nehmen, wenn du das so verwenden willst, oder einfach vec4. Kannst auch mit floats padden oder einfach das memcpy selber bauen.
(Tbh nimm einfach vec4 in deiner Datenstruktur)
_________________ offizieller DGL Compliance Beauftragter Never run a changing system! (oder so)
u.a. die caches sind halt darauf optimiert immer mit 16 byte alignten daten zu arbeiten -> schneller
Das wird wohl etwa der gleiche Effekt sein, wie die Word-Ausrichtung von Bytes auf einer 16-Bit CPU ? Sehe ich das Richtig, das bei einer normalen Uniformübergabe, ein float gleich viel Zeit braucht, wie ein vec4 ?
Zitat:
Oder sollte man im Shader auch mit Dummys auf vec4 aufrunden ?
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2622 Wohnort: Berlin
Programmiersprache: Go, C/C++
Da die Operationen auf vec4 laufen, würde mindestens eine zusätzliche Operationen zum füllen der 4. Komponente benötigt werden, da nicht jede Operationen die ignorieren kann. Aber hier gehts mehr um cache alignment, cache effizienz. Da vec3f 16Byte aligned ist, müsste für das auslesen von diffuse erst 16byte geladen werden, 12 verworfen und dann nochmal 16byte geladen, 4 verworfen und dann noch shiften und verunden. Passt das ganze nicht dauerhaft in die register, weil die Funktion zuviele Register braucht, macht er das immer wieder. Das wäre super kostenintensiv und hätte 0 mehrwert. So zwingt man den Nutzer einfach 4byte zu verschwenden oder da noch was rein zu quetschen und benötigt keine weiteren Operationen. Das hätte ich auch beim Swizzle begrüsst, wenn man von einem Pixelformat in das Zielformat hochladen kann und im Shader nur noch das eine Format hat.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Wen ich es richtig verstehe, macht der Shader aus jeder Variable, egal ob byte, float oder vecx, einen 16Byte-Block, dies braucht zwar mehr Speicher, aber dafür ist es um einiges schneller ? Betrifft dies nur die Unifom-Blöcke, oder generell alle Variablen im GLSL-Code ?
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2622 Wohnort: Berlin
Programmiersprache: Go, C/C++
So einfach ist es nicht. Die Rechenwerke laden aus dem Speicher Cachelines, egal welcher Typ. Hier geht es um die größe der Variable und wie sie in einem Register liegt. Vec liegt 16byte aligned im register, da die rechenbefehle die so brauchen. Der Shader muss also anfangen hin und her zu kopieren, verunden und shiften, damit es passt, wenn die nicht passend kommen.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2622 Wohnort: Berlin
Programmiersprache: Go, C/C++
Ja so kannst du es machen. Ich empfehle dann dummy zu padding1 bis n umzubenennen. Alternative kannst du auch für TVector3f ein byte alignment von 16Byte einstellen und die dummy‘s weg lassen aber dann verbraucht es in Containern auch entsprechend die 4 byte und es kann sein, dass du das lesen der daten mit dem Typ machst, dann würde dies nicht mehr funktionieren. Von daher musst du gucken was besser passt. Microsoft hat in ihren structs immer pad0-n, padding0-n oder reserved0-n.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
https://www.freepascal.org/docs-html/3.0.2/prog/progsu1.html <- byte alignment of records
Genau dies wollte, ich probieren, aber es funktioniert nicht. Aber ich wollte es beim ganzen Record machen und nicht beim einzelnen TVector3f, da dieser auch anders wertig gebraucht wird.
Jetzt verstehe ich dies langsam mit den reinquetschen. Ich habe jetzt hinter "ambient" noch "shininess" gesetzt, somit kommt die auch auf 16Byte. Somit wird die Mesh auch richtig dargestellt.
Code:
type
TMaterial =record
ambient: TVector3f;// Umgebungslicht
shininess: GLfloat;// Glanz
diffuse: TVector3f;// Farbe
pad2: GLfloat;
specular: TVector3f;// Spiegelnd
pad3: GLfloat;
end;
Code:
layout (std140)uniform Material {
vec3 Mambient;// Umgebungslicht
float Mshininess;// Glanz
vec3 Mdiffuse;// Farbe
vec3 Mspecular;// Spiegelnd
};
Aber etwas verstehe ich immer noch nicht. Ich habe noch einer Array eingebaut, welche, welche 20Byte Gross ist. Müsste es diese nicht auch 32Byte aufrunden ? Ich habe Pascal-Seitig dafür 32Byte mit test reserviert.
Code:
layout (std140)uniform Material {
float test[5];// Als Versuch
vec3 Mambient;// Umgebungslicht
float Mshininess;// Glanz
vec3 Mdiffuse;// Farbe
vec3 Mspecular;// Spiegelnd
};
Code:
TMaterial =record
test:array[0..7]of GLfloat;
ambient: TVector3f;// Umgebungslicht
shininess: GLfloat;// Glanz
diffuse: TVector3f;// Farbe
pad2: GLfloat;
specular: TVector3f;// Spiegelnd
pad3: GLfloat;
end;
PS: Jetzt sehe ich es, für jeden Float in der Array werden 16Byte gebraucht. So funktioniert es.
Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast
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.