Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mär 28, 2024 17:28

Foren-Übersicht » Programmierung » Shader
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 43 Beiträge ]  Gehe zu Seite Vorherige  1, 2, 3  Nächste
Autor Nachricht
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Mo Dez 16, 2013 19:08 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
OpenglerF hat geschrieben:
Ich habe gerade so im Kopf, dass man Normalen mit der transponierten inversen Matrix multiplizieren muss.
Wenn die Matrix nur Rotation enthält, ist das Inverse = die transponierte Matrix. Bei Translation gilt das für den 3x3-Teil afaik immer noch. Insofern sollte das klappen (ich mach's in meinen Programmen genau so).

Edit: Ich habe mal von WolframAlpha eine Matrix mit Translation und Rotation invertieren lassen:
[url]https://www.wolframalpha.com/input/?i=inverse+{{x1%2Cx2%2Cx3%2Ca}%2C{y1%2Cy2%2Cy3%2Cb}%2C{z1%2Cz2%2Cz3%2Cc}%2C{0%2C0%2C0%2C1}}[/url]
Wie man sieht, steckt im 3x3-Teil nichts von der Translation drin.

mathias hat geschrieben:
Was kommt in inNormal?
Ein Normalenvektor (auch Normale) ist ein Vektor der Länge 1, welcher Senkrecht auf der Oberfläche steht, die du beschreiben willst. Zur Bestimmung der Normale n eines Dreiecks (A,B,C) gibt es folgende Formel:
n = normalize(cross(B-A, C-A));

Du benötigst die Normalen aber nicht pro Dreieck, sondern pro Vertex. Du kannst natürlich jedem Vertex eines Dreiecks den gleichen Normalenvektor geben. Dann sehen die Kanten hart aus (wie echte Kanten eben). Bei einem Würfel wäre das erwünscht. Bei runden Körpern dagegen i.d.R. nicht. Hier sollte man die Normalen aller an den Vertex grenzenden Dreiecke interpolieren (und anschließend normalisieren!), damit es "smooth" aussieht.

Diese Berechnungen führst du einmal auf der CPU aus und lädst sie dann in den VBO. Oder du lädst deine Modelle direkt aus Dateien, in denen schon Normalenvektoren gespeichert sind. Das war übrigens alles auch schon vor OpenGL3 nötig (nur um OGL3 jetzt nicht in unnötig schlechtes Licht zu stellen).

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Mo Dez 16, 2013 20:57 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Kann man die Normale so berechnen, ich hab dies aus einem alten OpenGlProgramm kopiert. Es gibt eine Farbänderung auf dem Würfel, aber so nach richtigem Licht sieht dies nicht aus.
Code:
  1. function NormalCut(p: TVector): TVector;
  2. var
  3.   l: GLfloat;
  4. begin
  5.   l := Sqrt(Sqr(p[1]) + Sqr(p[2]) + Sqr(p[3]));
  6.   if (l > -0.000001) and (l < 0.000001) then l := 1;
  7.   p[1] := p[1] / l;
  8.   p[2] := p[2] / l;
  9.   p[3] := p[3] / l;
  10.   Result := p;
  11. end;
  12.  
  13. procedure CubeNormale;
  14. var
  15.   i: integer;
  16. begin
  17.   for i := 1 to 36 do
  18.   begin
  19.     fCubeNormale[i] := NormalCut(fCube[i]);
  20.   end;
  21. end;    

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Mo Dez 16, 2013 22:25 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Die Funktion NormalCut tut nichts weiter, als einen Vektor zu normalisieren (auf Länge 1 kürzen). Die andere Funktion sieht nicht so geeignet aus. Sie erzeugt Normalenvektoren, die nicht senkrecht auf den Flächen stehen, sondern diagonal von den Ecken weg (unter der Voraussetzung, dass es sich um einen Würfel mit (0,0,0) als Mittelpunkt handelt). Auf diesem Weg würde man Normalenvektoren einer Kugel erzeugen, da sie keine harten Kanten bringt.

Die Normalen eines an den Achsen ausgerichteten Würfels sind so einfach, dass du sie im Prinzip per Hand eintragen kannst. Die "rechte" Seite bekommt (1,0,0), die "linke" entsprechend (-1,0,0). Für oben/unten machst du das gleiche mit der Y-Achse und für vorne/hinten hast setzt du die Z-Achse analog.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Mo Dez 16, 2013 22:36 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Bekommt jede Ecke eines Dreieckes eine Normale ?

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 18:03 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Ja, eine Normale pro Vertex.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 18:23 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe festgestellt, das die Variable LightColor nirgends verwendet wird. Vielleicht ist dies die Ursache, das es nicht funktioniert.
OpenglerF hat geschrieben:
Also bei Licht.....
Code:
  1.  
  2. in vec3 Normal;
  3. in vec3 Position; //Modelspace
  4. in vec4 Color;
  5. in vec2 TextureCoord;
  6.  
  7. uniform float AmbientStrength;
  8. uniform float DiffuseStrength;
  9. uniform float SpecularStrength;
  10. uniform float Shininess;
  11. uniform vec3 LightPosition;
  12. uniform vec4 LightColor;
  13.  
  14. uniform sampler2D Texture0;
  15.  
  16. out FragColor;
  17. void main()
  18. {
  19.     vec3 EyeNormal = normalize(Position);
  20.     vec3 NormalizedNormal = normalize(Normal);
  21.     vec3 LightDirection = normalize(Position - LightPosition);
  22.     vec3 ReflectedLight = normalize(reflect(LightDirection, NormalizedNormal));
  23.  
  24.     float DiffusePart = max(dot(NormalizedNormal, LightDirection), 0.0);
  25.     float SpecularPart = pow(max(dot(ReflectedLight , EyeNormal), 0.0), Shininess);
  26.  
  27.     float Light = AmbientStrength +
  28.                      DiffuseStrength * DiffusePart +
  29.                       SpecularStrength * SpecularPart;
  30.  
  31.     vec4 FinalColor = Color * texture2D(Texture0, TextureCoord);
  32.     FragColor = vec4(Light, Light, Light, 1) * FinalColor;
  33. }
  34.  


Unterdessen habe ich die Normaleberechnung abgeändert.
Code:
  1.  
  2. type
  3.   TVector = array[1..3] of GLfloat;
  4.  
  5.   fTMatrix = array[1..4, 1..4] of GLfloat;
  6.  
  7.   fTCube = array[1..36, 1..3] of GLfloat;    
  8.  
  9. var
  10.   FCubeNormale: fTCube;  
  11.  
  12. const
  13.   fCube: fTCube =
  14.     ((-0.2, -0.2, -0.2),......
  15.  
  16. function GetNormal(P0, P1, P2: TVector): TVector;
  17.  
  18.   function NormalCut(p: TVector): TVector;
  19.   var
  20.     l: GLfloat;
  21.   begin
  22.     l := Sqrt(Sqr(p[1]) + Sqr(p[2]) + Sqr(p[3]));
  23.     if (l > -0.000001) and (l < 0.000001) then l := 1;
  24.     p[1] := p[1] / l;
  25.     p[2] := p[2] / l;
  26.     p[3] := p[3] / l;
  27.     Result := p;
  28.   end;
  29.  
  30. var
  31.   a, b, erg: TVector;
  32. begin
  33.   a[1] := P1[1] - P0[1];
  34.   a[2] := P1[2] - P0[2];
  35.   a[3] := P1[3] - P0[3];
  36.   b[1] := P2[1] - P0[1];
  37.   b[2] := P2[2] - P0[2];
  38.   b[3] := P2[3] - P0[3];
  39.   erg[1] := a[2] * b[3] - a[3] * b[2];
  40.   erg[2] := a[3] * b[1] - a[1] * b[3];
  41.   erg[3] := a[1] * b[2] - a[2] * b[1];
  42.   Result := NormalCut(erg);
  43. end;
  44.  
  45.  
  46. procedure CubeNormale;
  47. var
  48.   n, i: integer;
  49.   v: TVector;
  50. begin
  51.   for i := 1 to 12 do
  52.   begin
  53.     n := i * 3 - 2;
  54.     v := GetNormal(FCube[n + 0], FCube[n + 1], FCube[n + 2]);
  55.     fCubeNormale[n + 0] := v;
  56.     fCubeNormale[n + 1] := v;
  57.     fCubeNormale[n + 2] := v;
  58.   end;
  59. end;    

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 18:46 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Sieht auf den ersten Blick ganz gut aus. Nicht benutzte Variablen optimiert der Treiber einfach weg. Wenn du LightColor nicht reinmultiplizierst, wird das Licht halt weiß.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 18:47 
Offline
DGL Member
Benutzeravatar

Registriert: So Sep 26, 2010 12:54
Beiträge: 238
Wohnort: wieder in Berlin
Programmiersprache: Englisch
und lass deine Arrays mal bei 0 anfangen, das ist üblich in c/c++/pascal/delphi/asm/c#/d .... 1 ist eher vba/vb6...


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 19:19 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Stimmt schon: Das Indices bei 0 anfangen, sollte man sich möglichst früh angewöhnen.
Alles Verbreitete was nicht aus der VB Welt stammt, arbeitet mit dem Basisindex 0. OpenGL zum Beispiel aber auch alle anderen Programmbibliotheken. Außerdem ist ab 0 vom Code her meist eleganter/kürzer und entspricht der Abbildung in Maschninencode. Es ist halt einfach unkonsistent mal gezwungener Maßen mit 0 zu rechnen und dann wieder mit 1. Und dann manchmal umzurechnen.
Wenn es am Shader scheitert, mein schon genannter Geheimtipp:
Einfach die zwischen Ergebnisse ausgeben lassen und schauen ob sie mit den Erwarteten übereinstimmen.
Debugger gibt es für GLSL im Gegensatz zu HLSL in DirectX leider praktisch keinen Brauchbaren, deshalb muss man sich so behelfen.


Zuletzt geändert von OpenglerF am Di Dez 17, 2013 20:25, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 20:06 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
glAwesome hat geschrieben:
Code:
  1. Position = meinMatrix * inPos;
  2. Normal = mat3(meinMatrix) * inNormal;

Da war der Fehler begraben. Da der Compiler bei der ersten Zeile eine Fehlermeldung gab, habe ich folgendes geschrieben:
Code:
  1.   Position = vec3(meinMatrix) * inPos;
  2.   Normal = mat3(meinMatrix) * inNormal;
anstelle
Code:
  1.   Position = mat3(meinMatrix) * inPos;
  2.   Normal = mat3(meinMatrix) * inNormal;

Die rechte Seite des Würfels hat eine falsche Farbe. Soviel ich weis kann man dies verbessern, in dem man beim Zeichen eines Dreiecks auf die Drehrichtung der Eckpunkte achtet.

Zitat:
und lass deine Arrays mal bei 0 anfangen, das ist üblich in c/c++/pascal/delphi/asm/c#/d .... 1 ist eher vba/vb6...
Als nächstes werde ich dies änden.


Dateianhänge:
Zwischenablage-1.jpg
Zwischenablage-1.jpg [ 8.11 KiB | 9148-mal betrachtet ]

_________________
OpenGL
Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 20:24 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Zitat:
ist das Inverse = die transponierte Matrix

Ne, das kann irgendwie nicht sein.
Die Inverse errechnet sich relativ kompliziert, wie es auch auf Wikipedia steht. Das hat nichts mit dem transponieren zu tun. Auf Wolframalpha komme ich übrigens zu dem Ergebnis im Anhang.
Wenn das überall steht wird das schon seinen Sinn haben.


Dateianhänge:
MSP8101e2bh072dc343e7f00002ef4ab4bf86065di.gif [9.4 KiB]
Noch nie heruntergeladen
Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 21:19 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
mathias hat geschrieben:
glAwesome hat geschrieben:
Code:
  1. Position = meinMatrix * inPos;
  2. Normal = mat3(meinMatrix) * inNormal;

Da war der Fehler begraben.

Stimmt, aber deine Korrektur ist auch falsch. Richtig müsste es heißen:
Code:
  1. Position = vec3(meinMatrix * vec4(inPos, 1.0));
  2. Normal = mat3(meinMatrix) * inNormal;
Denn Position und inPos sind vom Typ vec3, meinMatrix ist jedoch eine 4x4-Matrix. Sorry, dass ich dir da eine unnötige Falle gestellt habe!

OpenglerF hat geschrieben:
Die Inverse errechnet sich relativ kompliziert, wie es auch auf Wikipedia steht. Das hat nichts mit dem transponieren zu tun.
Von reinen Rotationsmatrizen ist das Inverse gleich die transponierte Matrix.
http://wiki.delphigl.com/index.php/Techniken_zur_Matrixinversion#Reine_Rotationsmatrizen

Ob das mit Translation für den 3x3-Teil immer noch gilt, da bin ich mir nicht 100%ig sicher. Jedoch hatte ich damit bisher noch keine Probleme. Wolframalpha zeigt außerdem, dass die Translation auf den 3x3-Teil keinen Einfluss hat - oder siehst du dort irgendein a, b oder c?

Bei Skalierung funktioniert das natürlich so nicht mehr.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Di Dez 17, 2013 21:30 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Achso, reine Rotation, dass kann sein. :wink:
Normalerweise ist halt noch mindestens Skalierung darauf. Und in eher seltenen Fällen auch manchmal noch Scherung.
Translation ist bei Normalvektoren ohnehin nicht angebracht. Das macht nur bei Positionsvektoren Sinn.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Mi Dez 18, 2013 00:18 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
glAwesome hat geschrieben:
Stimmt, aber deine Korrektur ist auch falsch. Richtig müsste es heißen:
Code:
  1. Position = vec3(meinMatrix * vec4(inPos, 1.0));
  2. Normal = mat3(meinMatrix) * inNormal;
Denn Position und inPos sind vom Typ vec3, meinMatrix ist jedoch eine 4x4-Matrix. Sorry, dass ich dir da eine unnötige Falle gestellt habe!

Wieso muss ich dies nur bei der ersten Zeile machen ?
Normal und in inNormal sind auch von vec3.

Code:
  1. #version 330
  2. // Input vom VBO:
  3. in vec3 inPos;
  4. in vec4 inColor;
  5. in vec3 inNormal;
  6.  
  7. uniform mat4 meinMatrix;
  8. uniform mat4 CameraMatrix;
  9.  
  10. // Ausgabe an den Fragmentshader:
  11. out vec4 Color;
  12.  
  13. out vec3 Position;
  14. out vec3 Normal;
  15.  
  16. void main(void)
  17. {
  18.  
  19.   Position = vec3(meinMatrix * vec4(inPos, 1.0));
  20.   Normal = mat3(meinMatrix) * inNormal;
  21.  
  22.   gl_Position = CameraMatrix * meinMatrix * vec4(inPos, 1.0);
  23.   Color = inColor;
  24.   Color = vec4(0.6, 0.0, 0.0, 1.0);
  25. }    

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Wieso funktioniert dies ?
BeitragVerfasst: Mi Dez 18, 2013 00:29 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Weil meinMatrix eine 4x4-Matrix ist. Damit kannst du nur 4-komponentige Vektoren transformieren. Also musst du erst inPos in einen vec4 umwandeln. Bei der Matrixtransformation kommt wieder ein vec4 raus. Dich interessieren aber nur die ersten 3 Komponenten. Deshalb die erneute Umwandlung nach vec3.

Wie die Multiplikation im Detail funktioniert, wird hier recht anschaulich gezeigt und mit etwas Überlegung kannst du dir daraus erschließen, warum man mit einer 4x4-Matrix nur einen vec4 mutliplizieren kann.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 43 Beiträge ]  Gehe zu Seite Vorherige  1, 2, 3  Nächste
Foren-Übersicht » Programmierung » Shader


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 15 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.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.219s | 19 Queries | GZIP : On ]