DGL
https://delphigl.com/forum/

Parallax Mapping mit fxPascal
https://delphigl.com/forum/viewtopic.php?f=20&t=2491
Seite 1 von 1

Autor:  Mars [ Mi Feb 11, 2004 22:46 ]
Betreff des Beitrags:  Parallax Mapping mit fxPascal

Nachdem vor kurzem eine neue Bumpmapping Methode auf OpenGL.org präsentiert (oder besser gesagt wieder entdeckt) wurde, wollte ich mal ausprobieren, wie das sogenannte "Parallax Mapping" mit fxPascal umgesetzt werden kann.
Erst war die Enttäuschung groß - fxPascal "verschluckte" Variablen, auf der Sourcefourge Seite gab es aber glücklicherweise eine neue Version (von heute!), bei der dieser Fehler nicht mehr auftrat.

Der Code für das Parallax Mapping sieht dann folgendermaßen aus (ich komme mir zwar wie ein Behinderter vor, wenn ich Shader programmiere und eine Stunde oder mehr für ein paar Codezeilen brauche, weil es ziemliches Neuland ist - mit fxPascal geht es aber relativ problemlos)

das Vertexprogramm:
Code:
  1. {$optimize-}
  2. program VertexProgram1;
  3. uses arb_vertex_program, arb_position_invariant;
  4.  
  5. // input:
  6. // texture #0 = color map
  7. // texture #1 = normal map
  8. // texture #2 = offset map
  9. // vertex.attrib[6] = tangent
  10.  
  11. // output:
  12. // texcoord[0] offset in texture map
  13. // texcoord[1] tangent space light0 vector
  14. // texcoord[2] tangent space eye vector
  15.  
  16. // remarks
  17. // binormal is computed on the fly
  18. // light is taken from light source 0
  19. // viewer position is taken from modelview.invtrans
  20.  
  21. var
  22.   binormal, eyevec,
  23.   light0pos, light0vec: vec4;
  24.  
  25. begin
  26.   // compute binormal
  27.   binormal := cross(vertex.attrib[6], vertex.normal);
  28.  
  29.   // vector pointing to light 0
  30.   with state do
  31.     light0pos := MatrixMult4(matrix.modelview.inverse, light[0].position);
  32.   light0vec := vertex.position - light0pos;
  33.  
  34.   // transform light0 vector into tangent space
  35.   with vertex do
  36.     result.texcoord[1] := MatrixMult3(Matrix(attrib[6], binormal, normal), light0vec);
  37.   result.texcoord[1].w := 1.0;
  38.  
  39.   // vector pointing to eye
  40.   eyevec := vertex.position - state.matrix.modelview.invtrans.row[3];
  41.  
  42.   // transform eye vector into tangent space
  43.   with vertex do
  44.     result.texcoord[2] := MatrixMult3(Matrix(attrib[6], binormal, normal), eyevec);
  45.   result.texcoord[2].w := 1.0;
  46.  
  47.   result.color:=vertex.color;
  48.   result.texcoord[0]:=vertex.texcoord[0];
  49. end;
  50.  


und das Fragmentprogramm:
Code:
  1. {$optimize-}
  2. program FragmentProgram1;
  3. uses arb_fragment_program;
  4.  
  5. // input:
  6. // texture #0 = color map
  7. // texture #1 = normal map
  8. // texture #2 = offset map
  9. // texcoord[0] offset in texture map
  10. // texcoord[1] tangent space light0 vector
  11. // texcoord[2] tangent space eye vector
  12.  
  13. var
  14.   eyevects,
  15.   rgb, normal, height, bump, total,
  16.   light0tsvec,
  17.   newtexcoord: vec4;
  18.  
  19. begin
  20.   // normalize tangent space eye vector
  21.   eyevects := normalize(fragment.texcoord[2]);
  22.  
  23.   // calculate offset and new texture coordinate
  24.   height := texture2d(2, fragment.texcoord[0]);
  25.   newtexcoord := (height * 0.04 - 0.02) * eyevects + fragment.texcoord[0];
  26.  
  27.   // get texture data
  28.   rgb := texture2d(0, newtexcoord);
  29.   normal := normalize(texture2d(1, newtexcoord) * 2.0 - 1.0);
  30.  
  31.   // normalize light0 vector
  32.   light0tsvec := normalize(fragment.texcoord[1]);
  33.  
  34.   // normal dot lightdir
  35.   bump := dot3(normal, light0tsvec);
  36.  
  37.   // compute total effect
  38.   total := sat(bump * state.light[0].diffuse + state.lightmodel.ambient);
  39.  
  40.   // and multiply by regular texture map color
  41.   result.color := sat(rgb * total);
  42. end;
  43.  


Leider muss ich die Codeoptimierung ausschalten, damit das Programm korrekt generiert wird (es gibt keinen Absturz, der Assembler Source scheint aber falsch zu rechnen). Das "Leider" ist hier ehrlich gemeint, denn an sich ist es eine wahre Freude, fxPascal dabei zuzusehen, Optimierungen in den Assemblercode einzubauen, auf die ich selbst gar nicht gekommen wäre. Normalerweise funktioniert es ja auch, bei komplexeren Shadern mit vielen Variablen, scheint da irgend etwas durcheinander zu kommen. Bei abgeschalteter Optimierung kompilieren die Shader aber korrekt, was auch keine geringe Leistung ist.

Es gibt natürlich auch einen Screenshot - Carad berechnet die Tangenten fürs TBN Mapping in ein Vertexattribut, wenn man genau hinsieht, erkennt man, dass 9 Shader benötigt werden, um Parallax Mapping zu implementieren:
1) RenderSettings: Einschalten der Vertex- und Fragmentprogramme
2) TextureSettings: Aktivierung TexUnit #0, 2D-Texturen
3) Textur: Decal-Map
4) TextureSettings: Aktivierung TexUnit #1, 2D-Texturen
5) Textur: Normal-Map
6) TextureSettings: Aktivierung TexUnit #3, 2D-Texturen
7) Textur: Height-Map
8) Vertex Programm
9) Fragment Programm

Das alles klappt auch einwandfrei, die Komponenten werden alle richtig berechnet, darauf bin ich auch recht stolz, zeigt es doch dass BaseGraph und Carad recht allgemeingültig sind, da auch "neue" Algorithmen interaktiv implementiert werden können, ohne dass sie fest verdrahtet im Programm vorliegen müssen.
Leider kann Carad noch keine Vertexattribute als DelphiSource abspeichern, sobald ich diese Funktion eingebaut habe stelle ich das fertige Demo mit Source online.

Dateianhänge:
Dateikommentar: ScreenShot aus der Carad IDE, beachtenswert die 9 Shader fürs Parallax Bumpmapping, sowie die neuen TSynEdit Fenster für fxPascal Source (viel schöner als der TRichText Hack).
ParMap.jpg
ParMap.jpg [ 46.74 KiB | 3810-mal betrachtet ]

Autor:  LarsMiddendorf [ Mi Feb 11, 2004 23:50 ]
Betreff des Beitrags: 

Ich werde mal versuchen den Fehler zu finden. Bei den Optimierungen scheint es da viele Spezialfälle zu geben. Mich wundert ein wenig, daß die neue Version 0.4 von heute sein soll. Die habe ich doch schon seit ein paar Wochen aktualisiert. Da es außer den Korrekturen zu den Fehler, die Mars gefunden hat, keine Änderungen gab, habe ich das hier nicht extra gepostet.

Autor:  Mars [ Do Feb 12, 2004 01:24 ]
Betreff des Beitrags: 

Hmm, jedenfalls meldete das CVS Programm, dass eine neue Version online sei - und das Datum war dann das Heutige (intern steht noch 0.3 drin).

Übrigens habe ich Carad nun soweit aktualisiert, dass es Vertexattribute speichert. Vielleicht hilft das ja ein Stück weit - ich habe das Projekt mit dglOpenGL und fxPascal erstellt, der fxPascal Code ist in Parallax.pas zu finden und kann dort ohne Weiteres direkt geändert werden.

http://mcad.delphigl.com/Parallax.zip
(Benötigt GL_ARB_vertex_program und GL_ARB_fragment_program Unterstützung)

@dglOpenGL
die Kompilierung der neuesten BaseGraph Bibliotheken mit der aktuellen Version klappte nicht, weil dort nur die GL_FOG_COORDINATE_xxx Konstante vorhanden sind (laut Spezifikation heißen die nun GL_FOG_COORD_xxx), außerdem gibt es VBOs nur als ARB-Variante (da Core Feature von GL 1.5 sollten die auch als ARB-lose Definitionen zur Verfügung stehen).
Ich habe beides hinzugefügt, vielleicht kann man die neue Version (1.3c) auch auf DelphiGL einpflegen.

[edit]
wer das Parallax Mapping auf älteren Grafikkarten in Aktion sehen möchte, muss nur die neuesten MesaGL DLLs (z.B. von hier: http://www.basegraph.com/bg/ger/info.html ins Projektverzeichnis kopieren - überraschenderweise ist das gar nicht so langsam wie befürchtet (im Standardfenster 2 bis 3 Frames pro Sekunde bei mir).

Seite 1 von 1 Alle Zeiten sind UTC + 1 Stunde
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/