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

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

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



Ein neues Thema erstellen Auf das Thema antworten  [ 52 Beiträge ]  Gehe zu Seite 1, 2, 3, 4  Nächste
Autor Nachricht
 Betreff des Beitrags: UnifomBlockObject
BeitragVerfasst: Di Okt 27, 2015 20:13 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe eine kleine Classe für UBO geschrieben.
Wen ich nur ein UBO im Project habe, dann funktioniert das Ganze auch.
Erzeuge ich aber ein zweites UBO, dann kommen sie gegenseitig in die Quere.

Code:
  1. type
  2.  
  3.   { TUBO }
  4.  
  5.   TUBO = class(TObject)
  6.   private
  7.     buffer : GLuint;
  8.   public
  9.     constructor Create(Shader: TShader; UniformName: PGLchar);
  10.     destructor Destroy; override;
  11.  
  12.     procedure LoadBuffer(data: PGLvoid; size: GLsizeiptr);
  13.   end;
  14.  
  15.  
  16. implementation
  17.  
  18. { TUBO }
  19.  
  20. constructor TUBO.Create(Shader: TShader; UniformName: PGLchar);
  21. begin
  22.   inherited Create;
  23.   glGenBuffers(1, @buffer);
  24.  
  25.   glUniformBlockBinding(Shader.ID, glGetUniformBlockIndex(Shader.ID, UniformName), 0);
  26.   glBindBuffer(GL_UNIFORM_BUFFER, buffer);
  27. end;
  28.  
  29. destructor TUBO.Destroy;
  30. begin
  31.   glDeleteBuffers(1, @buffer);
  32.   inherited Destroy;
  33. end;
  34.  
  35. procedure TUBO.LoadBuffer(data: PGLvoid; size: GLsizeiptr);
  36. begin
  37.   glBufferData(GL_UNIFORM_BUFFER, size, data, GL_DYNAMIC_DRAW);
  38.   glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
  39. end;
  40.  
  41. end.    


In InitScene habe ich folgenden Aufruf:
Code:
  1.   UBOLight := TUBO.Create(Shader, 'allUniforms');
  2.   UBOLight.LoadBuffer(@Mat, SizeOf(Mat));
  3.  
  4.   UBOScale := TUBO.Create(Shader, 'scale');
  5.   UBOScale.LoadBuffer(@scale, SizeOf(scale));


allUniforms beinhalte diverse Lichtparameter, welche sich auch ändern lassen.
scale ist ein Test-wert welcher probehalber in der Matrix etwas verändert.
Das Problem ist aber sobald ich die beiden Zeilen mit UBOScale aufrufe, wird das Licht modifiziert, anstelle von scale.
Ich denke, das ich in der Classe etwas falsch mache.

Shader.ID zeigt auf die ProgrammID des Shaders.

So wie es aussieht, haben die dort ein ähnliches Problem; http://stackoverflow.com/questions/9155 ... rm-buffers

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 11:38 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Der zweite Parameter von glBindBufferBase muss glaube ich das sein, was glGetUniformBlockIndex zurückgibt (nicht 0).

Edit: Okay, du verwendest glUniformBlockBinding, da weiß ich nicht, ob das noch stimmt. Habe mich selbst erst kürzlich halbwegs in UBOs eingearbeitet.

_________________
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: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 15:01 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Wen es eine andere Lösung gibt, würde ich es anders machen.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 18:44 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Code:
  1. glUniformBlockBinding(Shader.ID, glGetUniformBlockIndex(Shader.ID, UniformName), 0);

Dein Binding Point ist immer 0, der muss bei mehreren Block Objekten aber jeweils eindeutig sein. Mit obigem Code benutzen beide UBOs den selben Binding Point, UboScale überschreibt also UboLight.

Die Bindungen müssen zum Shader passen :
Code:
  1. layout(binding = 0) uniform MeinUBOa
  2. ...
  3. layout(binding = 1) uniform MeinUBOb
  4.  

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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 19:51 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
Die Bindungen müssen zum Shader passen :

Dies geht leider nicht, da wird Version 4.2 verlangt, aber ich habe nur 3.3.

Code:
  1. 0(18) : error C7532: layout qualifier 'binding' requires "#version 420" or later
  2. 0(18) : error C0000: ... or #extension GL_ARB_shading_language_420pack : enable


Aber für was sollte die BindingNr gut sein ?
Für was ist dann glGetUniformBlockIndex gut ?

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 21:02 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Dann leg die Binding Points selbst fest :

Code:
  1.   glUniformBlockBinding(Shader.ID, glGetUniformBlockIndex(Shader.ID, UniformName), bindingPointA);
  2.   glBindBufferBase(GL_UNIFORM_BUFFER, bindingPointA, buffer);
  3.  
  4.   glUniformBlockBinding(Shader.ID, glGetUniformBlockIndex(Shader.ID, UniformName), bindingPointB);
  5.   glBindBufferBase(GL_UNIFORM_BUFFER, bindingPointB, buffer);
  6.  


Wichtig ist dass jeder Block sein eigenes Binding hat.

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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 21:04 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
So wie es aussieht, habe ich es jetzt zum laufen gebracht.

Code:
  1.   TUBO = class(TObject)
  2.   private
  3.     BindingPoint,
  4.     buffer: GLuint;
  5.   const
  6.     BPInc: GLuint = 0; // Hochzähler für BindingPoint
  7.   public
  8.     constructor Create(Shader: TShader; UniformName: PGLchar);
  9.     destructor Destroy; override;
  10.  
  11.     procedure UpdateBuffer(Data: PGLvoid; size: GLsizeiptr);
  12.   end;
  13.  
  14.  
  15. implementation
  16.  
  17. { TUBO }
  18.  
  19. constructor TUBO.Create(Shader: TShader; UniformName: PGLchar);
  20. var
  21.   id: GLint;
  22. begin
  23.   inherited Create;
  24.   BindingPoint := BPInc;
  25.   Inc(BPInc);
  26.   glGenBuffers(1, @buffer);
  27.   id := glGetUniformBlockIndex(Shader.ID, UniformName);
  28.   if id = -1 then begin
  29.     ShowMessage(UniformName + ' ' + IntToStr(id));
  30.     Exit;
  31.   end;
  32.   glUniformBlockBinding(Shader.ID, id, BindingPoint);
  33. end;
  34.  
  35. destructor TUBO.Destroy;
  36. begin
  37.   glDeleteBuffers(1, @buffer);
  38.   inherited Destroy;
  39. end;
  40.  
  41. procedure TUBO.UpdateBuffer(Data: PGLvoid; size: GLsizeiptr);
  42. begin
  43.   glBindBuffer(GL_UNIFORM_BUFFER, buffer);
  44.   glBufferData(GL_UNIFORM_BUFFER, size, Data, GL_DYNAMIC_DRAW);
  45.   glBindBufferBase(GL_UNIFORM_BUFFER, BindingPoint, buffer);
  46. end;


Die Fehler-Abfrage geht noch nicht, ich habe es von glGetUniformLocation übernommen, dort wird ein glint zurückgeliefert und bei glGetUniformBlockIndex ein gluint.
Aber ein gluint kann logischerweise niemals -1 haben.

Im Shader hatte ich auch noch einen kleine Fehler, beim Shader muss es dringend ein struct sein:
Code:
  1. uniform scale{  // geht nicht
  2.   float s;
  3. };
  4.  
  5. uniform float scale  // geht
  6.  



Und so kann ich jetzt zu Laufzeit die werte ändern:

Code:
  1. procedure TForm1.SpeedButton4Click(Sender: TObject);
  2. begin
  3.   scale := Random(40) - 20;
  4.  
  5.   UBOScale.UpdateBuffer(@scale, SizeOf(scale));
  6. end;
  7.  
  8. procedure TForm1.SpeedButtonClick(Sender: TObject);
  9. begin
  10.   MatNr := StrToInt(TSpeedButton(Sender).Caption);
  11.   Mat := Material[MatNr];
  12.  
  13.   UBOLight.UpdateBuffer(@Mat, SizeOf(Mat));
  14. end;

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 21:21 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
Dann leg die Binding Points selbst fest :

Habe ich jetzt eingebaut, so wie ich es gemacht sieht obiges Post, geht.

Danke für die Infos. :D

Wäre es noch zu empfehlen ein std140 in den Shader zu schreiben ?
Code:
  1. layout(std140) uniform scale{
  2.   float s;
  3. };  

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 21:25 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
mathias hat geschrieben:
Wäre es noch zu empfehlen ein std140 in den Shader zu schreiben ?
Code:
  1. layout(std140) uniform scale{
  2.   float s;
  3. };  


Wenn es das ist was du willst, dann ja. Bei std140 wird nix wegoptimiert, was sehr praktisch ist wenn man Structs verwendet die dann in deiner Anwendung das selbe Layout haben wie im Shader. Die kann man dann 1:1 hochladen.

Details dazu : https://www.opengl.org/wiki/Interface_B ... ory_layout

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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Mi Okt 28, 2015 21:28 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
was sehr praktisch ist wenn man Structs verwendet die dann in deiner Anwendung das selbe Layout haben wie im Shader.

Das wäre eigentlich das Ziel, sonst würde ist nicht viel Sinn machen.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Do Okt 29, 2015 16:19 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
mathias hat geschrieben:
Code:
  1. procedure TUBO.UpdateBuffer(Data: PGLvoid; size: GLsizeiptr);
  2. begin
  3.   glBindBuffer(GL_UNIFORM_BUFFER, buffer);
  4.   glBufferData(GL_UNIFORM_BUFFER, size, Data, GL_DYNAMIC_DRAW);
  5.   glBindBufferBase(GL_UNIFORM_BUFFER, BindingPoint, buffer);
  6. end;

Zum updaten von Buffer Objects solltest du aber glBufferSubData verwenden. glBufferData ist nur zum Anlegen des Puffers sinnvoll, weil es neuen Speicher alloziert, statt den alten weiterzuverwenden.

_________________
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: UnifomBlockObject
BeitragVerfasst: Do Okt 29, 2015 16:56 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Meinst du so sei es besser ?
Code:
  1. constructor TUBO.Create(Shader: TShader; UniformName: PGLchar; size: GLsizeiptr);
  2. var
  3.   id: GLuint;  // ????
  4. begin
  5.   inherited Create;
  6.   BindingPoint := BPInc;
  7.   Inc(BPInc);
  8.   glGenBuffers(1, @buffer);
  9.   id := glGetUniformBlockIndex(Shader.ID, UniformName);
  10.   if id = GLuint(-1) then begin
  11.     ShowMessage(UniformName + ' ' + IntToStr(GLint(id)));
  12.     Exit;
  13.   end;
  14.   glUniformBlockBinding(Shader.ID, id, BindingPoint);
  15.  
  16.   glBindBuffer(GL_UNIFORM_BUFFER, buffer);
  17.   glBufferData(GL_UNIFORM_BUFFER, size, nil, GL_DYNAMIC_DRAW);
  18. end;
  19.  
  20. procedure TUBO.UpdateBuffer(Data: PGLvoid; size: GLsizeiptr);
  21. begin
  22.   glBindBuffer(GL_UNIFORM_BUFFER, buffer);
  23.   glBufferSubData(GL_UNIFORM_BUFFER, 0, size, Data);
  24.  
  25.   glBindBufferBase(GL_UNIFORM_BUFFER, BindingPoint, buffer);
  26. end;  

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: Fr Okt 30, 2015 11:27 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Ja, so meinte ich das mit glBufferSubData. Bei glBindBufferBase bin ich mir unsicher. Müsste es nicht reichen, das nur einmal in Create aufzurufen?

_________________
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: UnifomBlockObject
BeitragVerfasst: So Nov 01, 2015 17:40 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Hier nochmals der komplette Code meine UBO-Classe.
Es funktioniert alles prächtig, solange ich nicht allzu viele UBOs habe.
glBufferSubData habe ich versuchsweise mal ausgeklammert, aber das Ergebnis ist das Gleiche.
Code:
  1. type
  2.  
  3.   { TUBO }
  4.  
  5.   TUBO = class(TObject)
  6.   private
  7.     BindingPoint, buffer: GLuint;
  8.   public
  9.     constructor Create(Shader: TShader; UniformName: PGLchar; size: GLsizeiptr);
  10.     destructor Destroy; override;
  11.  
  12.     procedure UpdateBuffer(Data: PGLvoid; size: GLsizeiptr);
  13.   end;
  14.  
  15.  
  16. implementation
  17.  
  18. { TUBO }
  19.  
  20. constructor TUBO.Create(Shader: TShader; UniformName: PGLchar; size: GLsizeiptr);
  21. const
  22.   BPInc: GLuint = 0;
  23. var
  24.   id: GLuint;
  25. begin
  26.   inherited Create;
  27.   BindingPoint := BPInc;
  28.   Inc(BPInc);
  29.   glGenBuffers(1, @buffer);
  30.   LogForm.add('UBO:' + IntToStr(BPInc));
  31.   id := glGetUniformBlockIndex(Shader.ID, UniformName);
  32.   if id = GL_INVALID_INDEX then begin
  33.     ShowMessage(UniformName + ' ' + IntToStr(GL_INVALID_INDEX));
  34.     Exit;
  35.   end;
  36.   glUniformBlockBinding(Shader.ID, id, BindingPoint);
  37.  
  38.   //  glBindBuffer(GL_UNIFORM_BUFFER, buffer);
  39.   //  glBufferData(GL_UNIFORM_BUFFER, size, nil, GL_DYNAMIC_DRAW);
  40. end;
  41.  
  42. destructor TUBO.Destroy;
  43. begin
  44.   glDeleteBuffers(1, @buffer);
  45.   inherited Destroy;
  46. end;
  47.  
  48. procedure TUBO.UpdateBuffer(Data: PGLvoid; size: GLsizeiptr);
  49. begin
  50.   glBindBuffer(GL_UNIFORM_BUFFER, buffer);
  51.   glBufferData(GL_UNIFORM_BUFFER, size, Data, GL_DYNAMIC_DRAW);
  52.   //  glBufferSubData(GL_UNIFORM_BUFFER, 0, size, Data);
  53.  
  54.   glBindBufferBase(GL_UNIFORM_BUFFER, BindingPoint, buffer);
  55. end;
  56.  
  57. end.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: UnifomBlockObject
BeitragVerfasst: So Nov 08, 2015 16:49 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Irgendwas stimmt mit meinem UBO immer noch nicht.
Für kleinere Scenen mit ca. 20 Mesh, funktioniert alles prima.
Wen ich mit meinem OBJ-Loader ein Object lade, das sich aus ca. 800 Meshes zusammensetzt, kommt es zur Darstellungsfehler.
Mein schwacher Intel-Atom hat sogar mit weniger Elementen Probleme.

Jedes Mesh bekommt einen eigenen Shader.
Jeder Shader hat eine Beleuchtungsberechnung, dafür habe ich 2 UBOs eine für Licht, die andere das Material.

Ich habe jedes Mesh in eine Classe gepackt, somit hat jedes Mesh die eigene Beleuchtung-Daten.

Löse ich Ganze mit normalen Uniform-Übergaben, dann läuft alles Fehlerfrei, auch auf dem Atom.
Ist evt. die GPUs mit zu vielen UBOs überfordert ?

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 52 Beiträge ]  Gehe zu Seite 1, 2, 3, 4  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:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.103s | 17 Queries | GZIP : On ]