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

Aktuelle Zeit: Do Mär 28, 2024 23:49

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



Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Erste Versuche mit Geometrie-Shader
BeitragVerfasst: Fr Aug 22, 2014 20:22 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe ein bisschen mit dem Geometrie-Shader gebastelt.

Mein Object wird kopiert und anschliessend wird beim linken Object die Normale berechnet.
Beim rechten Object ist die Normale eine Konstante.

Die 3 Shader:

Code:
  1. // Vertex
  2.  
  3. #version 330
  4.  
  5. in vec3 inPos;
  6. in vec2 vertexUV0;
  7. in vec2 vertexUV1;
  8.  
  9. uniform mat4 Matrix;
  10.  
  11. out vec2 UV0;
  12. out vec2 UV1;
  13. out vec4 Position;
  14.  
  15. void main(void)
  16. {
  17.   gl_Position = Matrix * vec4(inPos, 1.0);
  18.   UV0 = vertexUV0;
  19.   UV1 = vertexUV1;
  20. }


Code:
  1. // Geometrie
  2.  
  3. #version 330
  4.  
  5. layout(triangles) in;
  6. layout(triangle_strip, max_vertices = 9) out;
  7.  
  8. in vec2 UV0[];
  9. in vec2 UV1[];
  10.  
  11. in vec4 Position[];
  12.  
  13. out vec2 vUV0;
  14. out vec2 vUV1;
  15.  
  16. out vec3 Pos;
  17. out vec3 Normal;
  18.  
  19. vec3 GetNormal(vec3 P0, vec3 P1, vec3 P2)
  20. {
  21.    vec3 a, b;
  22.    for (int i = 0; i <= 2; i++)
  23.    {
  24.       a[i] = P1[i] - P0[i];
  25.       b[i] = P2[i] - P0[i];
  26.    }
  27.    return normalize(vec3( a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]));
  28. }
  29.  
  30.  
  31. void main(void)
  32. {
  33.    vec4 p0,p1,p2;
  34.    p0 = gl_in[0].gl_Position;
  35.    p1 = gl_in[1].gl_Position;
  36.    p2 = gl_in[2].gl_Position;
  37.  
  38.    Normal = GetNormal(p0.xyz, p1.xyz, p2.xyz);
  39.  
  40.  
  41.    for(int i = 0; i < gl_in.length(); i++)
  42.    {
  43.      gl_Position = gl_in[i].gl_Position + vec4(-0.4, 0.0, 0.0, 0.0);
  44.  
  45.      vUV0 = UV0[i];
  46.      vUV1 = UV1[i];
  47.  
  48.      EmitVertex();
  49.    }
  50.  
  51.    EndPrimitive();
  52.  
  53.    Normal = vec3(0.5, 1.0, 0.5);
  54.  
  55.    for(int i = 0; i < gl_in.length(); i++)
  56.    {
  57.       gl_Position = gl_in[i].gl_Position + vec4(0.4, 0.0, 0.0, 0.0);
  58.  
  59.       vUV0 = UV0[i];
  60.       vUV1 = UV1[i];
  61.  
  62.       EmitVertex();
  63.    }
  64.    EndPrimitive();
  65. }


Code:
  1. // Fragment
  2.  
  3. #version 330
  4.  
  5. in vec3 Pos;
  6. in vec3 Normal;
  7.  
  8.  
  9. in vec2 vUV0;
  10. in vec2 vUV1;
  11.  
  12. uniform sampler2D Sampler0;
  13. uniform sampler2D Sampler1;
  14.  
  15. out vec4 FragColor;
  16.  
  17. uniform vec3 LightPosition = vec3(2.0, 2.0, 2.0);
  18. float UmgebungsLicht = 0.3;
  19.  
  20.  
  21. float diffuse()
  22. {
  23.   vec3 LP        = (LightPosition * 1.0) - Pos;
  24.   float distance = length(LP);
  25.   float dif      = max(dot(Normal, LP), UmgebungsLicht);
  26.   return           dif * (1.0 / (1.0 + (0.25 * distance * distance)));
  27. }
  28.  
  29. void main()
  30. {
  31.   FragColor = (texture( Sampler0, vUV0 ) + texture( Sampler1, vUV1 )) * 0.5 * diffuse();
  32. }


Ich kann mir vorstellen, das es noch einige hat was man noch verbessern könnte.

Ich sehe schon, mit der GPU kann man sehr viel anstellen. :shock:


Dateianhänge:
Zwischenablage-1.jpg
Zwischenablage-1.jpg [ 23.91 KiB | 13493-mal betrachtet ]

_________________
OpenGL
Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 22, 2014 23:00 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
mathias hat geschrieben:
Ich kann mir vorstellen, das es noch einige hat was man noch verbessern könnte.
Du könntest z.B. die for-Schleife in GetNormal() ersetzen durch
Code:
  1. vec3 a = P1 - P0;
  2. vec3 b = P2 - P0;
Ist viel einfacher, tut das gleiche und ist vor allem schneller, wenn der Compiler nicht intelligent beim optimieren ist. Für das Kreuzprodukt gibt es auch eine eingebaute Funktion.

_________________
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  
BeitragVerfasst: So Aug 24, 2014 16:30 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe GetNormal abgeändert, auch habe ich am Anfang von main noch was verbessert.

Code:
  1. vec3 GetNormal(vec3 P0, vec3 P1, vec3 P2)
  2. {
  3.    vec3 a, b;
  4.    a = P1 - P0;  // for Schleife ist weg.
  5.    b = P2 - P0;
  6.    return normalize(vec3( a[1] * b[2] - a[2] * b[1],
  7.                           a[2] * b[0] - a[0] * b[2],
  8.                           a[0] * b[1] - a[1] * b[0]));
  9. }
  10.  
  11.  
  12. void main(void)
  13. {
  14. // ----- alt
  15.    vec4 p0,p1,p2;
  16.    p0 = gl_in[0].gl_Position;
  17.    p1 = gl_in[1].gl_Position;
  18.    p2 = gl_in[2].gl_Position;
  19.    Normal = GetNormal(p0.xyz, p1.xyz, p2.xyz);
  20.  
  21. // ------- neu
  22.    Normal = GetNormal(gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, gl_in[2].gl_Position.xyz);                

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Aug 24, 2014 18:41 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
glAwesome hat geschrieben:
Für das Kreuzprodukt gibt es auch eine eingebaute Funktion.
*Wink mit dem Zaunpfahl* Die Funktion heißt übrigens cross().

_________________
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  
BeitragVerfasst: So Aug 24, 2014 19:11 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Schon wieder ein bisschen einfacher. Der cross Befehl spart einiges.

Code:
  1. vec3 GetNormal(vec3 P0, vec3 P1, vec3 P2)
  2. {
  3. //   vec3 a, b;
  4. //   a = P1 - P0;
  5. //   b = P2 - P0;
  6. //   return normalize(vec3( a[1] * b[2] - a[2] * b[1],
  7. //                          a[2] * b[0] - a[0] * b[2],
  8. //                          a[0] * b[1] - a[1] * b[0]));
  9.    return normalize(cross(P1 - P0, P2 - P0));
  10. }
  11.  

Noch einfacher währe in main
Code:
  1. Normal = normalize(cross(gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz, gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz));


2. Problem:

Kann man dies auch vereinfachen ?

Code:
  1.   vec3 p[3];
  2.  
  3.   for (int i = 0; i <= 2; i++)
  4.   {
  5.     p[i] = gl_in[i].gl_Position.xyz;
  6.   }  
  7.   Normal = GetNormal2(p);
  8.  



etwa so oder ähnlich ?
Code:
  1. p = gl_in.gl_Position.xyz;
  2. Normal = GetNormal2(p);


Hier noch GetNormal2:

Code:
  1. vec3 GetNormal2(vec3 P[3])
  2. {
  3.    return normalize(cross(P[1] - P[0], P[2] - P[0]));
  4. }

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Aug 26, 2014 22:00 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Falls das missverständen wurde, möchte ich betonen, dass es keinen Performance-Vorteil bringt, durch Inlining die Anzahl der mit Semikolon abgeschlossenen Anweisungen zu reduzieren.

Beispiel:
Code:
  1. // Variante 1
  2. vec3 a = P1-P0;
  3. vec3 b = P2-P0;
  4. vec3 c = cross(a,b);
  5.  
  6. // Variante 2
  7. vec3 c = cross(P1-P0, P2-P0);
Beide Varianten werden zu exakt demselben Maschinencode kompilieren und daher gleich schnell laufen. In solchen Fällen ist daher stets die übersichtlichere oder besser wartbare Variante zu bevorzugen. Welche das ist, darüber kann man streiten.

Ebenso sind Zuweisungen als kostenlos zu betrachten, wenn sie keinerlei Rechenoperationen beinhalten, sondern nur kopieren:
Code:
  1. vec4 p0 = gl_in[0].gl_Position;
Solch triviale Sachen optimiert der Compiler sowieso weg. Deine "Verbesserung" der main-Funtion bezüglich der Parameter von GetNormal() ist also keine (jedenfalls nicht in Bezug auf Geschwindigkeit).

_________________
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  
BeitragVerfasst: Mi Aug 27, 2014 08:02 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
glAwesome hat geschrieben:
Falls das missverständen wurde, möchte ich betonen, dass es keinen Performance-Vorteil bringt, durch Inlining die Anzahl der mit Semikolon abgeschlossenen Anweisungen zu reduzieren.

Beispiel:
Code:
  1. // Variante 1
  2. vec3 a = P1-P0;
  3. vec3 b = P2-P0;
  4. vec3 c = cross(a,b);
  5.  
  6. // Variante 2
  7. vec3 c = cross(P1-P0, P2-P0);
Beide Varianten werden zu exakt demselben Maschinencode kompilieren und daher gleich schnell laufen. In solchen Fällen ist daher stets die übersichtlichere oder besser wartbare Variante zu bevorzugen. Welche das ist, darüber kann man streiten.

Ebenso sind Zuweisungen als kostenlos zu betrachten, wenn sie keinerlei Rechenoperationen beinhalten, sondern nur kopieren:
Code:
  1. vec4 p0 = gl_in[0].gl_Position;
Solch triviale Sachen optimiert der Compiler sowieso weg. Deine "Verbesserung" der main-Funtion bezüglich der Parameter von GetNormal() ist also keine (jedenfalls nicht in Bezug auf Geschwindigkeit).

Dazu will ich noch als Hinweis geben, dass Optimierungen nicht aus einem gemeinsammen Compiler passieren, sondern jeder Grafikkarten Hersteller eigene Treiber mit eigenen Compilern liefert und die Qualität der Optimierung geht von wahnsinn bis gar keine.
Apple's iOS Shader Compiler z.b. konnte bis zur meiner letzten nutzung(knapp 1-2Jahren) nix, nicht mal das obige Beispiel oder if(true)... else ... optimieren.
Unity3D hat extra deswegen ein Shader Optimizer geschrieben, der auf den Mesa Parser und Optimizer basiert, weil dies auch wohl auf den meisten Android Geräten der Fall war.
Da der immer noch für alle Mobile Platformen aktive verwendet wird, geh ich davon aus, dass dies wohl immer noch der Fall ist.
Die Optimierungen kann man sich also nur sparen, wenn man explizit auf Nvidia, Intel und AMD Karten setzt.
http://developer.amd.com/tools-and-sdks/graphics-development/gpu-shaderanalyzer/ kann helfen aber seit 2Jahren auch nicht mehr geupdated wurden, schätze es ist ein Teil von CodeXL nun und ich find es einfach unter den vielen anderen Tools ned :\

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 27, 2014 14:54 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Nvidia bietet auch noch Nsight, das unter-anderem Shader-Debugging erlaubt. CodeXL sollte das, soweit ich weiß, nicht beherrschen.

Bei der Gelegenheit möchte ich auch nochmal darauf hinweisen das auf halbwegs moderner Hardware auch auch "cross" und die meisten solcher Funktionen grundsätzlich erstmal keinen Performancevorteil bieten. Die Zeit bei dem komplexe Vektorinstruktionen gibt ist anscheinend vorbei, man vereinfacht lieber den Befehlssatz und integriert noch mehr parallel laufende Shaderprozessoren. Wenn man genau das selbe per Hand macht, ist "cross" natürlich aus Lesbarkeitsgründen zu bevorzugen. Interessantes Material dazu:
ftp://download.nvidia.com/developer/cuda/seminar/TDCI_Arch.pdf
http://www.humus.name/Articles/Persson_LowLevelThinking.pdf
http://www.humus.name/Articles/Persson_LowlevelShaderOptimization.pdf


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 27, 2014 16:32 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
CodeXL kann Shader Debugging, ich hab es noch nicht benutzt, weil ich noch auf mein AMD System warte aber in der Tutorial Sektion von der Hilfe wird es Schritt für Schritt erklärt und das gab es auch schon im vorigen gDebugger.

Auf der GDC2014 war ein Talk von Nvidia wo die Speaker Optimierungspunkte erklärt haben und bei Shadern meinte der eine, dass die wichtigste Optimierung das parallelisieren des Shaders ist.
Es gibt in der Shader Language Funktionen die synchronisieren müssen, auf Werte zurück greifen, die ein Warten auslösen und natürlich Hardware bedingte Sync. Operationen wie z.B. Texel zugriff.
Dies sind Hotspots und für diese muss man optimieren, weil diese das skalieren auf Grakas reduzieren.
Ein gutes Beispiel ist z.B. Texels aus verschiedenen Blöcken einer DXT Textur zu zugreifen, das erzeugt mehr Cache misses und die Shader Unit muss für ein VRAM Sync warten.
Je mehr Shader Units aus dem gleichen Texturblock lesen, je höher die Performance, weil zum einen kein Sync passiert und zum zweiten der Cache um längen schneller ist als VRAM.
So kann also ein schlecht gewählter noise lookup für SSAO starke Performanceunterschiede hervor rufen.
Es ist ab einer zu testenden Reichweite schneller ein horizontalen blur über mehere Schritte nacheinander zu machen als in ein Step und gleiches für den vertikalen Schritt.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 27, 2014 19:21 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
OpenglerF hat geschrieben:
Nvidia bietet auch noch Nsight, das unter-anderem Shader-Debugging erlaubt. CodeXL sollte das, soweit ich weiß, nicht beherrschen.
Wann gibt es diese Tools endlich als Standalone? Ich habe und will kein Visual Studio/Eclipse...

OpenglerF hat geschrieben:
Bei der Gelegenheit möchte ich auch nochmal darauf hinweisen das auf halbwegs moderner Hardware auch auch "cross" und die meisten solcher Funktionen grundsätzlich erstmal keinen Performancevorteil bieten.
Dennoch sollte cross() verwendet werden. Diese eingebauten Funktionen sind alle optimal, d.h. es ist nicht möglich, die Funktionalität mit anderem Code nachzubauen, der schneller läuft. Der Nachbau von solchen Funktionen kann also höchstens gleich schnell sein. Und dass aktuelle Nvidia-Hardware skalar statt vektoriell arbeitet, mag derzeit stimmen, jedoch gibt's auch noch ältere Hardware und in Zukunft kann das auch wieder anders aussehen. Und bei anderen Herstellern ist es vielleicht auch anders. Nur damit sich hier niemand berufen fühlt, eingebaute Funktionen nicht zu benutzen.

Edit: Habe jetzt das Dokument http://www.humus.name/Articles/Persson_LowLevelThinking.pdf durch. Wenn das (auch für OpenGL) stimmt, was da steht, sollten neue OpenGL-Versionen hier ansetzen. Es kann doch wohl nicht wahr sein, dass ein Shader-Compiler unter dem Vorwand der IEEE-Kompatibilität solche einfachen Zusammenhänge nicht erkennt:
Code:
  1. -a.x * a.y == -(a.x * a.y)
  2. 50.0 * normalize(vec) == vec * (50.0 * invsqrt(dot(vec, vec)))
Standardmäßig sollte der Compiler floats mathematisch als reelle Zahlen betrachten und keine Rücksicht auf eventuelle Genauigkeitsfehler aufgrund der endlichen Genauigkeit usw. nehmen. Das ist das, was man als Programmierer in 99% der Fälle will. Falls man es wirklich exakt haben möchte, kann man immer noch ein #pragma precise oder so einfügen. Ich habe jedenfalls als Entwickler keine Lust, die Folgen dieses Unsinns durch mühsame Handarbeit auszubaden.

_________________
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  [ 10 Beiträge ] 
Foren-Übersicht » Programmierung » Shader


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 13 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:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.098s | 21 Queries | GZIP : On ]