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

Aktuelle Zeit: Do Mär 28, 2024 20:16

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



Ein neues Thema erstellen Auf das Thema antworten  [ 14 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: UBO struct mehrmals verwendet
BeitragVerfasst: Sa Mär 24, 2018 21:10 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich verwende die struct mit den Lichparametern 3mal.
Dieser Code funktioniert, aber das mit den 3 "uniform light? { ... }" gefällt mir nicht.
Dazu habe ich mehreres probiert.
Einmal oben bei layout, das wird nicht mal kompiliert.
Und weiter unten die 3 ausgeklammerten Zeilen, dies wird kompiliert, aber mit glUniformBlockIndex nicht gefunden.

Gibt es da eine elegantere Lösung, oder muss ich es sein lassen ?
Was ich machen könnte, ich könnte alle 3 Lichter in ein UBO nehmen, aber ich will es erst mal getrennt.
Code:
  1. #version 330
  2.  
  3. #define ambient vec3(0.2, 0.2, 0.2)
  4.  
  5. #define PI      3.1415
  6. #define Cutoff  cos(PI / 2 / 16)
  7.  
  8. in Data {
  9.   vec3 pos;
  10. } DataIn;
  11.  
  12. //layout(std140) struct   light0, light1, light2 {
  13. layout(std140) struct   Light {
  14.   bool On;
  15.   vec3 Pos;
  16.   vec3 Color;
  17.   float CutOff;
  18. };
  19.  
  20. uniform light0 {
  21.   Light light10;
  22. };
  23.  
  24. uniform light1 {
  25.   Light light11;
  26. };
  27.  
  28. uniform light2 {
  29.   Light light12;
  30. };
  31.  
  32. //uniform Light light0;
  33. //uniform Light light1;
  34. //uniform Light light2;
  35.  
  36. out vec4 outColor;  // ausgegebene Farbe
  37.  
  38. vec3 isCone(vec3 LightPos) {
  39.  
  40.   vec3 lp = LightPos;
  41.  
  42.   vec3 lightDirection = normalize(DataIn.pos - lp);
  43.   vec3 spotDirection  = normalize(-LightPos);
  44.  
  45.   float angle = dot(spotDirection, lightDirection);
  46.   angle = max(angle, 0.0);
  47.  
  48.   if(angle > Cutoff) {
  49.     return vec3(1.0);
  50.   } else {
  51.     return vec3(0.0);
  52.   }
  53. }
  54.  
  55. void main(void)
  56. {
  57.   outColor = vec4(ambient, 1.0);
  58.   if (light10.On) {
  59.     outColor.rgb  += isCone(light10.Pos) * light10.Color;
  60.   }
  61.   if (light11.On) {
  62.     outColor.rgb += isCone(light11.Pos) * light11.Color;
  63.   }
  64.   if (light12.On) {
  65.     outColor.rgb += isCone(light12.Pos) * light12.Color;
  66.   }
  67. }

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: So Mär 25, 2018 10:54 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Layout gehört zum Uniform nicht zur Struct (die nicht GLSL spezifisch ist), kann man also z.B. so machen:

Code:
  1.  
  2. struct Light {
  3.     bool On;
  4.     vec3 Pos;
  5.     vec3 Color;
  6.     float CutOff;
  7. };
  8.  
  9. layout (std140) uniform LightBlock {
  10.     Light lights[3];
  11. };
  12.  
  13. void main()
  14. {
  15.     for (int i = 0; i < 3; i++) {
  16.         vec3 lColor = lights[i].Color;
  17.     }
  18. ...
  19. }
  20.  


Da der Uniform Block anonym ist kann man direkt auf die Member zugreifen.

Alternativ, z.B. wenn es mal viele Lichtquellen werden sollten, besser ein SSBO nutzen. UBOs bei NV sind max. 64k und auf AMD afaik seit einiger Zeit eh nur noch als SSBO emuliert (deshalb da keine Limitierung der Größe).

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: So Mär 25, 2018 15:55 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
So wie ich es sehe, muss ich es einzeln machen, wie in meinen Post, wen ich für jede Lichtquelle ein eigener UBO will ?
Dein Beispiel könnte ich nehmen, wen ich alle Lichtquellen in ein UBO packen will, dies wäre natürlich effizienter.

Zitat:
Alternativ, z.B. wenn es mal viele Lichtquellen werden sollten, besser ein SSBO nutzen. UBOs bei NV sind max. 64k und auf AMD afaik seit einiger Zeit eh nur noch als SSBO emuliert (deshalb da keine Limitierung der Größe).
Leider wird da mindestens OpenGL 4.3 verlangt, nur kann mein Intel-Chip nur 4.2 und für ein OpenGL 3.3 Tutorial, daher nicht brauchbar.

Aber interessant ist es trotzdem. So wie es aussieht, müsste man da auch keine Padding verwenden, um eine 16Byte Block zu füllen ?
Wen UBO auf 64KB begrenzt ist, würden immerhin 1'000 Lichtquellen reinpassen ( 4 x 16 x 1'000 = 64'000 ).
Oder kennst du ein Beispiel, in dem man an das 64KB-Limit kommt ?

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Mo Mär 26, 2018 21:25 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
mathias hat geschrieben:
Wen UBO auf 64KB begrenzt ist, würden immerhin 1'000 Lichtquellen reinpassen ( 4 x 16 x 1'000 = 64'000 ).
Oder kennst du ein Beispiel, in dem man an das 64KB-Limit kommt ?


Die Definition deiner Lichtquellen ist sehr simpel, für echte Lichtquellen benötigt man noch weitere Parameter, dann hat man pro Quelle schnell recht viele Bytes.

Und bei einem deferred oder forward clustered Renderer können das durchaus mehrere hunderte Lichtquellen sein die sichtbar sind, da wird das mit dem UBO knapp.

SSBOs haben den großen Vorteil dass man die im Compute Shader schreiben kann, und so dann auf der GPU z.B. Culling etc. machen kann.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Di Mär 27, 2018 16:10 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
Und bei einem deferred oder forward clustered Renderer können das durchaus mehrere hunderte Lichtquellen sein die sichtbar sind, da wird das mit dem UBO knapp.
Wen sie zu Laufzeit geändert werden müssen, dann ja. Wen es aber statische Lichtquellen sind, ZB Kandelaber , würde ich die Werte direkt in den Shader als Konstante reinkompilieren.
Oder mache ich da einen Denkfehler ?

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Mi Mär 28, 2018 00:05 
Offline
Compliance Officer
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 460
Programmiersprache: C / C++ / Lua
Man macht halt immer das, was einem gerade gelegen kommt und wie es in den Speicher passt. Deine Idee mit dem "ich kompiliere die Lichtquelle statisch rein" ist halt unbrauchbar, wenn du Daten zur Laufzeit veraendern willst (weil shader neukompilieren doch etwas dauert), gds. aber brauchbar wenn die Daten halt statisch sind (aber mehr aufwand).

Ich persoenlich wuerde halt in 3.3 gar keine UBOs verwenden, sondern wenn ueberhaupt SSBOs (ueber extension vllt?) und ansonsten entweder "normal" uniform arrays nutzen oder den klassischen weg ueber texturen. Das ist sehr einfach zu implementieren und birgt den Vorteil, dass du wahrscheinlich nicht in Performancebegrenzer reinlaeufts.
(imho der weg des geringsten widerstands = bester weg)

_________________
offizieller DGL Compliance Beauftragter
Never run a changing system! (oder so)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Mi Mär 28, 2018 16:45 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
Ich persoenlich wuerde halt in 3.3 gar keine UBOs verwenden, sondern wenn ueberhaupt SSBOs (ueber extension vllt?)
In einem Tutorial will ich nicht unbedingt Extensionen verwenden.

Zitat:
und ansonsten entweder "normal" uniform arrays nutzen
Meinst du damit, das ich anstelle der struct eine Array verwende ?
In etwa so ?
    Element 0-3 --> Abient
    Element 4-7 --> Diffuse
    Element 8-11 --> Specular
    Element 12 --> Shininess
Eigentlich Schade, das es kein direkter Weg mit glUniformxxx für struct gibt. :roll:

Zitat:
oder den klassischen weg ueber texturen.

Texturen ?
Was soll das gehen ?

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Do Mär 29, 2018 00:20 
Offline
Compliance Officer
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 460
Programmiersprache: C / C++ / Lua
Ungefaehr so mit den Arrays funktioniert es auf jeden Fall, wichtig ist ja nur, dass die Daten irgendwie ankommen.

Genau wie bei Texturen, die sind schliesslich auch nur Buffer. Du kannst Daten reinschreiben und wieder im Shader auslesen...

_________________
offizieller DGL Compliance Beauftragter
Never run a changing system! (oder so)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Do Mär 29, 2018 07:31 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
mathias hat geschrieben:
Eigentlich Schade, das es kein direkter Weg mit glUniformxxx für struct gibt. :roll:

Doch, gibt es?
Code:
  1. glUniform3f(glGetUniformLocation(program, "lights[0].Color"), r, g, b);

_________________
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: UBO struct mehrmals verwendet
BeitragVerfasst: Do Mär 29, 2018 17:34 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
glAwesome hat geschrieben:
mathias hat geschrieben:
Eigentlich Schade, das es kein direkter Weg mit glUniformxxx für struct gibt. :roll:

Doch, gibt es?
Code:
  1. glUniform3f(glGetUniformLocation(program, "lights[0].Color"), r, g, b);

Ist dieser Befehl nicht, um in eine einfache vec3 Uniform zu schreiben, wen man jeden Wert einzeln übergeben will ?

Dann doch lieber so:
Code:
  1.  glUniform3fv(UniformID.VecColor, 1, @Color);  // Color : TVertex3f

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Do Mär 29, 2018 19:08 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Ja. Du hast natürlich Recht, dass es keinen glUniformStruct() oder sowas gibt, mit dem man ein komplettes struct auf einen Schlag mit Werten belegen kann. Ich wollte nur klarstellen, dass man durchaus Index- und Elementzugriffsoperatoren (also [] und .) in glGetUniformLocation() verwenden darf. Du brauchst nicht zwinged UBOs, nur weil eine uniform-Variable ein struct ist.

_________________
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: UBO struct mehrmals verwendet
BeitragVerfasst: Do Mär 29, 2018 19:27 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe mal folgendes versucht, dies liefert -1, somit ungültig.
Code:
  1. layout (std140) uniform Material {
  2.   vec3  Mambient;   // Umgebungslicht
  3.   vec3  Mdiffuse;   // Farbe
  4.   vec3  Mspecular;  // Spiegelnd
  5.   float Mshininess; // Glanz
  6. };


Code:
  1. //    ShowMessage(IntToStr(glGetUniformBlockIndex(Shader.ID, 'Material')));
  2.     ShowMessage(IntToStr(glGetUniformLocation(Shader.ID, 'Material')));
  3.  


Dies funktioniert wie erwartet auch nicht, auch wen ich die ID mit glGetUniformBlockIndex auslese.
Code:
  1. type
  2.   TMaterial = record
  3.     ambient: TVector3f;      // Umgebungslicht
  4.     pad0: GLfloat;           // padding 4Byte
  5.     diffuse: TVector3f;      // Farbe
  6.     pad1: GLfloat;           // padding 4Byte
  7.     specular: TVector3f;     // Spiegelnd
  8.     shininess: GLfloat;      // Glanz
  9.   end;
  10. ...
  11.   mRubin.ambient := vec3(1,1,1);
  12.   glUniform1fv(Material_ID, SizeOf(mRubin), @mRubin);

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Fr Mär 30, 2018 12:53 
Offline
Compliance Officer
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 460
Programmiersprache: C / C++ / Lua
Das liegt daran, dass die Bloecke aufgesplittet werden und dann Material.foo[0] oder so heissen. Schau dir mal an wie das aussieht indem du mit glGetActiveUniform dir alle moeglichen Uniforms anzeigen laesst inklusive Namen.
https://www.khronos.org/registry/OpenGL ... niform.xml

_________________
offizieller DGL Compliance Beauftragter
Never run a changing system! (oder so)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UBO struct mehrmals verwendet
BeitragVerfasst: Fr Mär 30, 2018 19:35 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Das Wiki gibt es sogar in deutsch: https://wiki.delphigl.com/index.php/glGetActiveUniform

Ich habe s probiert, mit folgendem Ergebnis:
Code:
  1. procedure TForm1.MenuItem3Click(Sender: TObject);
  2. var
  3.   s: ansistring;
  4.   i, Count, len, size, typ: integer;
  5.   sl: TStringList;
  6.  
  7. begin
  8.   sl := TStringList.Create;
  9.   SetLength(s, 255);
  10.  
  11.   glGetProgramiv(Shader.ID, GL_ACTIVE_UNIFORMS, @Count);
  12.  
  13.   for i := 0 to Count - 1 do begin
  14.     glGetActiveUniform(Shader.ID, i, 255, len, size, typ, @s[1]);
  15.     sl.Add(copy(s, 0, len) + '    ' + IntToStr(typ));
  16.   end;
  17.   ShowMessage(sl.Text);
  18.   sl.Free;
  19. end;


Ausgabe:
Code:
  1. ModelMatrix    35676
  2. Matrix    35676
  3. Mshininess    5126
  4. Mspecular    35665
  5. Mdiffuse    35665
  6. Mambient    35665


Die Unifom-Blöcke, kann man auch ausgeben.
Code:
  1.   glGetProgramiv(Shader.ID, GL_ACTIVE_UNIFORM_BLOCKS, @Count);
  2.  
  3.   for i := 0 to Count - 1 do begin
  4.     glGetActiveUniformBlockName(Shader.ID, i, 255, @len, @s[1]);
  5.     sl.Add(copy(s, 0, len) + '    ' + IntToStr(typ));
  6.   end;
  7.   ShowMessage(sl.Text);

Ausgabe:
Code:
  1. Material    35665


Dies sind noch recht praktische Funktionen, wen man einen Fehler sucht.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 14 Beiträge ] 
Foren-Übersicht » Programmierung » Shader


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 11 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.027s | 17 Queries | GZIP : On ]