OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Elmi
Beiträge: 12
Registriert: 13.06.2023, 07:30

OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Elmi »

Hi,

nach dem ich gestern Dank der Hilfe dieses Forums meine grundlegenden Verständnisprobleme lösen konnte, hänge ich jetzt an technischen Details fest.

Mein Problem: ich habe ein 3D-Modell, welches mit Normals daherkommt. Wenn ich dieses in einen entsprechenden Viewer lade, dann ist das Ergebnis so, wie ich das erwarten würde:

Bild
Das sieht gut aus, die Normals in dem Modell scheinen also nicht kaputt zu sein.

Mache ich das selbe mit meiner Applikation, dann ist das Ergebnis noch echt mies - und die ausgefransten Dreiecke lassen mich vermuten, dass das nicht nur an einer möglicherweise anderen Richung der Beleuchtung liegt:

Bild

Aktuell arbeite ich mit folgenden Shaderprogrammen:

Code: Alles auswählen

#version 130
in vec3 aPos;
in vec3 aNormal;
uniform mat4 inputTransform;
out vec3 Normal;
out vec3 fPos;
void main()
{
   gl_Position=inputTransform*vec4(aPos,1.0);
   Normal=aNormal;
   fPos=vec3(inputTransform*vec4(aPos,1.0));
}\0
Der Vertexshader nimmt in "aPos" die 3D-Daten entgegen und in "aNormal" die Normals. Die Normals werden über "Normal" an den Fragmentshader weitergeleitet. "inputTransform" ist eine Transformationsmatrix, mit welcher ich aus der aufrufenden Applikation heraus Position/Rotation/Skalierung der ganzen Szene verändere um die Ansicht auf das Modell entsprechend der Usereingaben zu modifizieren.
"fPos" reicht die transformierten Vektordaten ebenfalls weiter an den Framgentshader:

Code: Alles auswählen

#version 130
uniform vec4 inputColor;
in vec3 Normal;
in vec3 fPos;
out vec4 FragColor;
const vec3 lightPos = vec3(0.0,0.0,5.0);
const vec3 specColor = vec3(1.0,1.0,1.0);
void main()
{
   vec3 normal = normalize(Normal);
   vec3 viewDir = normalize(-fPos);
   if (dot(normal,viewDir)<0.0) normal*=-1.0;
   vec3 lightDir = normalize(lightPos - fPos);
   float lamb = max(dot(lightDir, normal), 0.0);
   float spec = 0.0;
   if (lamb > 0.0)
   {
       vec3 refDir = reflect(-lightDir, normal);
       float specAngle = max(dot(refDir, viewDir), 0.0);
       spec = pow(specAngle, 4.0);
    }\n"
    FragColor=inputColor+vec4(spec*specColor,1.0);
}\0
Der Fragmentshader entstammt im wesentlichen der Antwort auf https://stackoverflow.com/questions/612 ... -in-opengl angepasst auf meinen speziellen Fall.

"inputColour" erlaubt es, die Farbe des Modells von außen zu ändern. Die Position der Lichtquelle ist mit "lightPos" fix vorgegeben, ebenso wie "specColor".

Meine Frage: woran könnte das liegen? Irgend welche Hinweise, an welcher Stelle mein Problem liegen könnte?

Danke!
Benutzeravatar
Schrompf
Moderator
Beiträge: 4856
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Schrompf »

Debugge mal mit NVidia NSight oder dem AMD-Äquivalent rein. Die können beide für einzelne Pixel oder Vertizes den Shader Befehl für Befehl durchgehen und Dir anzeigen, welche Werte da rauskommen.

Alternativ mal klassisch Einzelwerte aus dem Programm als Farbe ausgeben und Augen zusammenkneifen, ob die Farben als Zahlenwerte gelesen hinkommen können oder nicht.

Das regelmäßige Muster im Modell sieht für mich aus, als hättest Du irgendwo ein Modulo drin. Also Deine Werte sind deutlich außerhalb des Zahlenbereichs [0...1] und werden runtergebrochen. Aber in Deinem Shadercode sehe ich nicht, wo das herkommen könnte.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Matthias Gubisch »

Ich vermute mal die inputTransform Matrix enthaelt world, view und projection?
Die fPos fuer die Beleuchtung sollte nur mit der world matrix des models multipliziert werden ohne view und projection

Die "Fransen" an den Raendern lassen auf nicht genutztes Anti-Aliasing schliessen.

Ansonsten kann ich auch nur den Tipp von Schrompf wiederhohlen, gib einfach mal dein Positionen und Normalen als Farben aus und schau ob das grob passen kann. Wenn du hilfe bei der interpretation brauchst poste einfach Screenshots davon.

Das AMD Pedant zu Nsight ist uebrigens RenderDoc und der passt fuer beide Hersteller (vermutlich auch Intel aber hier noch nie getestet)
Auf dauer kann ich dir nur empfehlen dich in solche Tools einzuarbeiten, fuer deinen Fall sollte aber OldScool mit Farbausgabe reichen ;)
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
joeydee
Establishment
Beiträge: 1044
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von joeydee »

Das schräge Muster könnte auch darauf hindeuten, dass dein Normalen-Buffer nicht ganz zum Vertex-Buffer passt, oder der Indexbuffer dazu nicht stimmt, so irgendwas.

Ich würde mal von einem einfacheren (kleineren) Modell ausgehen, dessen Buffer und Normalen du manuell debuggen kannst. Einzelnes Quad oder Unit-Würfel.
Elmi
Beiträge: 12
Registriert: 13.06.2023, 07:30

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Elmi »

Matthias Gubisch hat geschrieben: 14.06.2023, 11:11 Ich vermute mal die inputTransform Matrix enthaelt world, view und projection?
Die fPos fuer die Beleuchtung sollte nur mit der world matrix des models multipliziert werden ohne view und projection
Ähm...gute Frage :-)

Ich stelle keine virtuelle Landschaft oder ähnliches dar, sondern zeige einfach nur ein paar 3D-Modelle an, ohne dass in Bezug zu irgend einer Landschaft/Welt/Hintergrund/wasauchimmer stehen.

D.h. ich habe genau eine Matrix (eben jene "uniform mat4 inputTransform"), die für alle 3D-Objekte in identischer Weise verwendet wird und in die ich auch alles reinpacke:

- verschiebt der Anwender die Position der Darstellung, so wird der Transformationsanteil der Matrix angepasst
- rotiert der Anwender die Position der Darstellung, so wird der Rotationsanteil der Matrix angepasst
- zoomt der Anwender in die Darstellung hinein/aus ihr heraus, so wird der Skalierungsanteil der Matrix angepasst

Sollte ich das irgendwie trennen?
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Matthias Gubisch »

Vereinfacht gesagt besteht deine Transformation der Vertexpositonen zum Bildschirm aus 3 Schritten:

1. Die world/model Matrix des Objekts. Diese gibt die Position des Objektes in der Welt an. Wenn das die Einheitsmatrix ist gilt: VertexPosition == Weltkoordinate
2. Die View Matrix: Diese bestimmt im wesentlichen die Position und Ausrichtung deiner Kamera (also von wo die wie auf die Welt schaust)
3. Die Projektionsmatrix: Diese Bestimmt wie die 3D Koordinaten zu 2. Pixeln gemapped werden

Fuer die Fragment Position (also dass was du nach gl_Position schreibst musst du alle 3 beachten) Fuer deine fPos die dein Beleuchtungsshader benutzt darfst du nur die model Matrix benutzten.

Hier noch etwas Lesestoff zu den Matrizen
https://jsantell.com/model-view-projection/
http://www.opengl-tutorial.org/beginner ... -matrices/

Diese Tutorial Seite kann ich sehr empfehlen, enthaelt alles was die OGL Anfaenger Herz begehrt und noch mehr ;)
https://learnopengl.com/
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Elmi
Beiträge: 12
Registriert: 13.06.2023, 07:30

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Elmi »

Sorry, hat ein wenig gedauert, da ich anderweitig beschäftigt war. Zu der Beschreibung hier:
Matthias Gubisch hat geschrieben: 15.06.2023, 08:11 1. Die world/model Matrix des Objekts. Diese gibt die Position des Objektes in der Welt an. Wenn das die Einheitsmatrix ist gilt: VertexPosition == Weltkoordinate
Diese Matrix habe ich. Genau genommen hängen sämtliche Objekte meiner Welt an dieser Matrix, da sich keines der Objekte separat bewegen kann und alle immer in identischer Weise verändert werden. Das ist also die "inputTransform" meines Vertex-Shaders, welche von der Applikation von außen geändert wird, um die Ansicht auf die Objekte zu ändern.
2. Die View Matrix: Diese bestimmt im wesentlichen die Position und Ausrichtung deiner Kamera (also von wo die wie auf die Welt schaust)
Die habe ich nicht. Die Kamera verändert sich nicht, also habe ich mir diese Matrix gespart (bzw. kann man das je nach Standpunkt auch anders herum interpretieren: es gibt keine Objektmatrix, statt dessen existiert nur die Kameramatrix).
3. Die Projektionsmatrix: Diese Bestimmt wie die 3D Koordinaten zu 2. Pixeln gemapped werden
Auch die gibt es nicht. Zumindest wüsste ich nicht, wo ich die unterbringen soll.
Benutzeravatar
TomasRiker
Beiträge: 36
Registriert: 18.07.2011, 11:45
Echter Name: David Scherfgen
Wohnort: Hildesheim

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von TomasRiker »

Elmi hat geschrieben: 04.07.2023, 12:40
3. Die Projektionsmatrix: Diese Bestimmt wie die 3D Koordinaten zu 2. Pixeln gemapped werden
Auch die gibt es nicht. Zumindest wüsste ich nicht, wo ich die unterbringen soll.
Die hast du garantiert (sonst würdest du überhaupt nichts Sinnvolles auf dem Bildschirm sehen), aber sie spielt keine Rolle bei der Beleuchtung.

An deiner Stelle würde ich den Shader erstmal stark vereinfachen und einfach nur "N dot L"-Lighting machen (in deinem Code: max(dot(lightDir, normal), 0.0)) und den ganzen Rest mit Specular erstmal weglassen. Wie sieht es dann aus?
Benutzeravatar
Jonathan
Establishment
Beiträge: 2371
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Jonathan »

TomasRiker hat geschrieben: 04.07.2023, 13:16 Die hast du garantiert (sonst würdest du überhaupt nichts Sinnvolles auf dem Bildschirm sehen)
Ja würde ich auch so sehen. Wenn man die weglässt müsste man sowas wie eine orthografische Projektion haben und wenn die Szene richtig gebaut ist, könnte man wohl schon auch etwas sinnvolles sehen, aber das ist dann eher ein absurder Ausnahmefall - außerdem ist ja im gezeigten Screenshot ganz klar Perspektive zu erkennen.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Elmi
Beiträge: 12
Registriert: 13.06.2023, 07:30

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Elmi »

TomasRiker hat geschrieben: 04.07.2023, 13:16 Die hast du garantiert (sonst würdest du überhaupt nichts Sinnvolles auf dem Bildschirm sehen), aber sie spielt keine Rolle bei der Beleuchtung.
OK, dann nehme ich einfach mal an, dass ich eine Projektionsmatrix habe, aber suche sie nicht weiter, weil sie für mein Problem unerheblich ist :-)
An deiner Stelle würde ich den Shader erstmal stark vereinfachen und einfach nur "N dot L"-Lighting machen (in deinem Code: max(dot(lightDir, normal), 0.0)) und den ganzen Rest mit Specular erstmal weglassen. Wie sieht es dann aus?
Also mit einem Shader

Code: Alles auswählen

#version 130
uniform vec4 inputColor;
in vec3 Normal;
in vec3 fPos;
out vec4 FragColor;
const vec3 lightPos = vec3(0.0,0.0,5.0);
void main()
{
   vec3 normal = normalize(Normal);
   vec3 lightDir = normalize(lightPos - fPos);
   FragColor=inputColor*max(dot(lightDir, normal), 0.0);
}
erhalte ich sowas: Bild

Mal abgesehen davon, dass der Ring an einigen Stellen genau so hell ist wie der Hintergrund und deswegen nicht sichtbar ist, sind die sichtbaren Segmente immer noch recht seltsam beleuchtet.
Benutzeravatar
TomasRiker
Beiträge: 36
Registriert: 18.07.2011, 11:45
Echter Name: David Scherfgen
Wohnort: Hildesheim

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von TomasRiker »

Ja, sieht immer noch seltsam aus. Was mich auch wundert: Man scheint die Unterseite zu sehen. Die dürfte aber eigentlich gar nicht sichtbar sein. Hast du den Z-Buffer abgeschaltet oder so?

Edit: Ich habe nochmal über die Projektionsmatrix nachgedacht. Irgendwo muss sie sein, denn sonst hättest du kein Bild, und das "irgendwo" kann eigentlich nur in der einzigen Matrix sein, die du benutzt, nämlich inputTransform. Das hieße dann, dass du die Beleuchtung im falschen Koordinatensystem berechnen würdest, nämlich im projektiven Raum.
Wie berechnest du die Matrix, die du als inputTransform setzt?
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Matthias Gubisch »

Z-buffer scheint ein guter Tipp zu sein wenn ich mir das Bild so ansehe...

Ansonsten nochmal der Hinweis: Lies die Links die ich weiter oben gepostet habe und versuche mal deine Matrix (bzw eigentlich brauchst du ja 2 Matrizen als Shader input) entpsrechend zusammenzubauen.

Die ganzen Koordinatenraeume muss man verstanden haben ansonsten wird es extrem schwierig wenn man mehr als NdotL als beleuchtung machen will.
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Benutzeravatar
Schrompf
Moderator
Beiträge: 4856
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Schrompf »

ZBuffer könnte es sein, ODER: Du multiplizierst die Helligkeit auch in den Alphakanal rein, und kriegst damit teiltransparente Flächen je nach Helligkeit. [Edit] Jupp, exakt das isses. Änder mal auf:

Code: Alles auswählen

FragColor = inputColor;
FragColor.rgb *= max(...);
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Elmi
Beiträge: 12
Registriert: 13.06.2023, 07:30

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Elmi »

Schrompf hat geschrieben: 04.07.2023, 22:49 Du multiplizierst die Helligkeit auch in den Alphakanal rein, und kriegst damit teiltransparente Flächen je nach Helligkeit. [Edit] Jupp, exakt das isses.
Ja, das hat das Transparenzproblem tatsächlich gelöst. Mit dieser Änderung erhalte ich wieder ein sehr dunkles Objekt, bei dem nur wenig Lichtreflektion zu sehen ist. Ich habe das mal ein wenig aufgehellt, damit man was erkennen kann:

Code: Alles auswählen

FragColor=(inputColor*5*max(dot(lightDir, normal), 0.0))+0.1;
FragColor.a=1;
Dann sieht das Ergebnis im wesentlichen so seltsam kantig aus wie oben:

Bild

Wenn ich das Objekt nach oben verschiebe, wird es heller und rosa :-)

Bild
Benutzeravatar
Schrompf
Moderator
Beiträge: 4856
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Schrompf »

Gib mal nur die inputColor als Farbe aus. Oder nur die normal, dann halt *0.5 + 0.5. Ach ja, und Dein lässiges "+0.1" hinten dran... ich weiß nicht ausm Kopf, was das bei ner Vektoroperation macht. Schreib da besser mal ausführlich "+float3(0.1f, 0.1f, 0.1f, 0f)" stattdessen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
joeydee
Establishment
Beiträge: 1044
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von joeydee »

Weiß nicht ob es unterging, aber:
Falls die Lichtberechnung oder eine Normalentransformation falsch ist, müsste sie wenigstens bei gleichen Normalen aus dem Buffer auch gleich falsch sein.
Das heißt, z.B. an der Kante zweier Facetten müsste die gleiche (bei smooth shading: gleiche Normalen) oder zumindest ähnliche (bei flat shading: individuelle Normalen) Farbe zu sehen sein. Nach deinem Referenz-Screenshot vermute ich Flat-Shading, d.h. auch deine Quads müssten je Fläche zumindest dieselbe Farbe haben, da sie offentsichtlich auch dieselben Normalen haben.
Stattdessen sehe ich ein auffälliges Streifenmuster, also verschiedene Farben je Vertex bei demselben Quad. Außen je Facette erkennbar, innen sogar über die Diagonale, d.h. die Normalen scheinen sich da sichtbar zu unterscheiden. Vielleicht falsch berechnet, vielleicht falsch zugewiesen, evtl. ein Buffer-/Indexproblem.
Also: erstmal Normalen debuggen. Sprich, was Schrompf zuletzt sagte: den durchgereichten Normalenwert mal als Farbe rendern.
Auch wiederhole ich nochmal diesen Tipp: wie sieht ein einfacheres Objekt aus derselben Quelle aus? Z.B. ein einzelnes Quad? Ein Würfel? Eine Kugel?

Und zu den Shadern: Poste am besten immer beide Shader zusammen (Vertex und Fragment), damit man weiß was der aktuelle Stand ist und man auf einen Blick nachvollziehen kann welche Werte woher kommen beim Durchreichen vom VS zum FS.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4856
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Schrompf »

Beide Shader zusammen finde ich auch nützlich. Mir dämmert gerade, dass es auch sein könnte, dass Du die VertexPos ohne ModelMatrix verwendest. Dann würde sich auch so eine lokal wiederkehrende Lichterscheinung ergeben.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Elmi
Beiträge: 12
Registriert: 13.06.2023, 07:30

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Elmi »

So, ich denke, Dank der vielen hilfreichen Hinweise hier, komme ich der Sache näher: scheinbar habe ich tatsächlich einen Kuddelmuddel bei meinen Buffern und die Shader greifen auf alles mögliche zu, nur nicht auf die Normals.

Aktuell schiebe ich erst sämtliche Koordinaten als x y und z in einen Speicherbereich m_vertexArray (float-Datentyp). Der enthält dann z.B. 108 Elemente bei einem Würfel. Anschließend kommen die Normals dazu, das sind bei dem gleichen Würfel noch mal 36 float-Werte im gleichen Buffer hinten dran. Der Bufferinhalt ist dann also irgendwie so aufgebaut:

Code: Alles auswählen

x
y
z
x
y
z
x
y
z
...
nx
ny
nz
nx
ny
nz
...
Den Buffer setze ich mit

Code: Alles auswählen

glBindBuffer(GL_ARRAY_BUFFER,entity->m_gl3Element.coordVBO);
glBufferData(GL_ARRAY_BUFFER,m_vertexArray.size()*sizeof(float),m_vertexArray.data(), GL_STATIC_DRAW);
Das ergibt für mich noch irgendwie Sinn: es wird der Anfang des Buffers übergeben sowie die Gesamtlänge des Buffers.

Dann muss ich OpenGL mitteilen, wo welche Daten zu finden sind. Das geschieht für die Koordinaten über diesen seltsamen Aufruf hier, der ganz offensichtlich richtig ist, da die Geometrien an sich ja in Ordnung sind:

Code: Alles auswählen

const GLint location=glGetAttribLocation(entity->m_gl3Element.shaderProgram, "aPos");
glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(location);
Auf ähnlichem Weg muss ich mitteilen, wo in diesem Buffer die Normals zu finden sind. Und um so länger ich mir hier den Aufruf von glVertexAttribPointer() für die Normals ansehe, um so weniger Sinn ergibt er, da hier nirgends dieser Offset von 108 Speicherstellen bzw. 432 Bytes auftaucht, der bei obiger Datenanordnung im Buffer ja irgendwo stehen müsste:

Code: Alles auswählen

const GLint location = glGetAttribLocation(entity->m_gl3Element.shaderProgram, "aNormal");
glVertexAttribPointer(location,3,GL_FLOAT,GL_FALSE,0,(void*)(3 * sizeof(float)));
glEnableVertexAttribArray(location);
Aus der Beschreibung von glVertexAttribPointer() kann ich jetzt nicht wirklich erkennen, wo der Offset hinmuss, aber das, was in meinem Aufruf drinsteht, ist mit ziemlicher Sicherheit Müll!?

Das wirft also die Frage auf: wie teile ich OpenGL korrekt mit, dass meine Normals ab Indexposition 108 zu finden sind?
Benutzeravatar
Schrompf
Moderator
Beiträge: 4856
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Schrompf »

Indem Du einen zweiten Buffer-Slot verwendest und dort dann den VertexBuffer mit Offset bindest.

Normalerweise packt man alle Daten eines Vertex zueinander. Du baust Dir also eine Struktur

Code: Alles auswählen

struct Vertex {
float px, py, pz;
float nx, ny, nz;
};
Und die Grafikkarte holt sich dann diese Daten als Block für jeden VertexShader-Lauf. Deine VertexStruktur ist dann 6x sizeof(float) groß, die Position hat Offset 0Bytes, und die Normale hat Offset 12Bytes (3x float).

Du kannst auch die Positionen in einen Buffer und die Normalen in einen anderen Buffer packen. Aber immer nur eins zu eins! Wenn Du 36 Positionen hast, brauchst Du auch 36 Normalen. Du kannst nicht mischen, wie es Dir gefällt. Du kannst nicht "Position 24, und dazu Normale 5" angeben, es ist immer automatisch zwangsweise unvermeidlich "Position auf Index 24, Normale auf Index 24".

Mesh Shader ignorieren wir jetzt mal.

Also lautet meine Empfehlung: bau Dir eine Vertex-Struktur mit allen Daten für einen Vertex, und dann melde deren Einzelteile mit mehreren glVertexAttribPointer()-Aufrufen an.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Elmi
Beiträge: 12
Registriert: 13.06.2023, 07:30

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Elmi »

Dann passt aktuell ja auch noch nicht mal die Organisation meiner Normalen. Kann also nur Sch*** aussehen :-D

Danke!
joeydee
Establishment
Beiträge: 1044
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von joeydee »

Ich habe auch immer nur einein einzigen interleaved-Buffer. Mal ein Beispiel auseinandergenommen:
position (3 floats)
normale (3 floats)
vertexcolor (4 floats)
uvcoords (2 floats)
=je Vertex px, py, pz, nx, ny, nz, r, g, b, a, u, v
1 Quad (4 Verts) = 48 floats
Beispiel eines Quads (4x4, im Ursprung, auf XY-Ebene, Normale -Z, Farbe Orange (0.7,0.3,0.1,1)):

Code: Alles auswählen

-2 / 2 / 0 / 0 / 0 / -1 / 0,7 / 0,3 / 0,1 / 1 / 0 / 0 / 2 / 2 / 0 / 0 / 0 / -1 / 0,7 / 0,3 / 0,1 / 1 / 1 / 0 / 2 / -2 / 0 / 0 / 0 / -1 / 0,7 / 0,3 / 0,1 / 1 / 1 / 1 / -2 / -2 / 0 / 0 / 0 / -1 / 0,7 / 0,3 / 0,1 / 1 / 0 / 1
Dabei wird als "stride" die Anzahl der Floats bezeichnet, die zu einem Vertex gehören, hier also 12.
Um nun daraus etwas dem Vertexshader bekanntzumachen, sollte das je Attribut in dieser Form erfolgen:
(ist c# mit OpenTK-Wrapper, sollte aber in Original-OpenGL genauso sein)

Code: Alles auswählen

id = GL.GetAttribLocation(shaderhandle, attributeName);//Name im Vertexshader finden
GL.VertexAttribPointer(id, len, VertexAttribPointerType.Float, false, stride * sizeof(float), pos * sizeof(float));
//len: Länge des Attributs (z.b. 3 für pos)
//das "false" steht für normalize, mache ich aber immer an anderer Stelle
//stride: Schritt bis zum nächsten Vertex( Länge aller Attribute summiert, z.B. 3+3+4+2)
//pos: position dieses Attributs innerhalb des Strides (z.B. 6 für color, da vorher 3+3 Werte für pos und normal stehen)
Konkret für das obige Beispiel (wenn ich mich jetzt nicht vertan habe):

Code: Alles auswählen

id = GL.GetAttribLocation(shaderhandle, "position");
GL.VertexAttribPointer(id, 3, VertexAttribPointerType.Float, false, 12* sizeof(float), 0* sizeof(float));//lies ab position 0 im 12er-Stride 3 Werte
id = GL.GetAttribLocation(shaderhandle, "normal");
GL.VertexAttribPointer(id, 3, VertexAttribPointerType.Float, false, 12* sizeof(float), 3* sizeof(float));//lies ab position 3 im 12er-Stride 3 Werte
id = GL.GetAttribLocation(shaderhandle, "color");
GL.VertexAttribPointer(id, 4, VertexAttribPointerType.Float, false, 12* sizeof(float), 6* sizeof(float));//lies ab position 6 im 12er-Stride 4 Werte
id = GL.GetAttribLocation(shaderhandle, "uv");
GL.VertexAttribPointer(id, 2, VertexAttribPointerType.Float, false, 12* sizeof(float), 10* sizeof(float));//lies ab position 10 im 12er-Stride 2 Werte
Edit: zum Nachvollziehen hier nochmal der obige Stride und dessen Positionen:

Code: Alles auswählen

            //  position       normal          color              uv
            //  0   1   2      3   4   5       6   7   8   9      10  11
            //  px, py, pz,    nx, ny, nz,     r,  g,  b,  a,     u,  v
Jedes Vertexattribut im aktuellen Shader muss so "angesprochen" werden, sonst fehlen dort Daten.
Umgekehrt aber nicht: Man muss nicht jedes Attribut, das im Buffer steckt, bekanntmachen, wenn der Shader es nicht benötigt.
Reihenfolge egal, sowohl diese Aufrufe, als auch im Shader. Dafür gibts ja id und pos.
Elmi
Beiträge: 12
Registriert: 13.06.2023, 07:30

Re: OpenGL/Normals: Beleuchtetes Modell sieht Sch*** aus

Beitrag von Elmi »

Ich habe es jetzt tatsächlich in zwei getrennte Buffer aufgeteilt - unterschiedliche Daten in den gleichen Buffer zu packen erschien mir irgendwie unübersichtlich. Und siehe da, kaum dass man die Normals nicht einfach irgendwo hinpackt und dann auch noch nicht mal verwendet, passt das Ergebnis auch :-D

Danke für die Hilfe!
Antworten