Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

1

10.06.2013, 00:24

[OpenGL] Fragen rund um Buffer

Hallo zusammen,

stelle in letzter Zeit viele Fragen, sorry dafür aber ich wechsel gerade von openGL 2 auf openGL 4.3 ^^
Implementiere testweise ein Partikel-System in OpenGL 4.3, welches in einem ComputeShader simuliert wird. Anfangs habe ich eine feste Anzahl partikel spawnen lassen und konnte so 16Mio GL_POINTS mit 40FPS zu Boden regnen lassen (ohne Kollision).
Jetzt wollte ich jedoch die Partikel emittieren lassen und nicht gleichzeitig spawnen. Dabei habe ich überlegt wie man das geschickt macht und wollte zunächst mit glBufferData nach jedem emittieren einen geeignet großen Buffer generieren, habe mich davon jedoch schnell wieder verabschiedet weil es doch uneffizient klingt, oder? ^^. Derzeit erstelle ich somit einen Buffer der die maximale Anzahl Partikel beinhalten kann.
Weiterhin stelle ich überrascht fest, dass meine Buffer jetzt (also sobald ich emittiere und nicht komplett alle Partikel initial spawne) anscheinend nur noch halb so viel Platz haben ?(

Mal ein wenig Code ^^

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// Einmalige Initialisierung
////////////////////////////

glGenBuffers(1,&posSSbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER,posSSbo);
glBufferData(GL_SHADER_STORAGE_BUFFER,maxParticles*sizeof(vec4),NULL,GL_STREAM_DRAW);

// ... velocities, colors, ...

// Compute Shader

computeShader = new Shader("Shader/computeShader.comp");
    
// Bind Buffers
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, posSSbo);

// ... velocities, colors, ...



// Emittieren jedes Frame
////////////////////////////

glBindBuffer(GL_SHADER_STORAGE_BUFFER,posSSbo);

// Hiermit fülle ich nur einen Bereich des Buffers, 
// numParticles ist hierbei die derzeitige Anzahl aller partikel *vor* dem emittieren
// particles ist hierbei die Anzahl der partikel *nach* dem emittieren
// Alle parameter haben auch dauerhaft richtige Werte und sind <  maxParticles*sizeof(vec4)

points = (vec4*) glMapBufferRange(GL_SHADER_STORAGE_BUFFER,numParticles*sizeof(vec4),particles*sizeof(vec4),bufMask);

for( GLuint i = 0; i < emittedParticles; i++ )
{
   random = sphericalRand<GLfloat>(1.0f);
   points[ i ].x = random.x;
   points[ i ].y = random.y;
   points[ i ].z = random.z;
   points[ i ].w = 1.;
}
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);

// ... velocities, colors, ...



// Simulieren
//////////////

// nach Shader aktivierung
glDispatchCompute(numParticles / 128, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

// Zeichnen
/////////////

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,posSSbo);
glVertexAttribPointer(0,4,GL_FLOAT,GL_FALSE,0,(void*)0);

// ... velocities, colors, ...

// Draw Points
glDrawArrays(GL_POINTS, 0, numParticles);
glDisableVertexAttribArray(0);


Vorher hat das ganze brav funktioniert bis zur maximalen Anzahl der Partikel, bin mir auch noch nicht ganz sicher wie ich die Partikel "sterben" lasse und diese somit aus dem Buffer raushole ?(
Seit dem emittieren habe ich wirklich ab 0.5 * maxParticles eine Zugriffsverletzung beim Schreiben an der Stelle "points[ i ].x = random.x;"

Hoffe mein Problem ist etwas klar geworden. OpenGL Fehler treten übrigens nicht auf
Danke für jede Hilfe und Klarstellung,

Greets Sc4v

Edit: Achja ich konnte keinen Performanz unterschied zwischen GL_STATIC_DRAW, GL_DYNAMIC_DRAW und GL_STREAM_DRAW feststellen... was wäre denn in diesem Szenario theoretisch schneller?

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

2

10.06.2013, 15:19

Zu deiner letzten Frage: theoretisch soll GL_STATIC_DRAW am schnellsten sein. Da das nun mal nicht immer so ist kannst du dich allerdings nicht darauf verlassen. Ich versuche möglichst immer static buffer anzulegen.
Für dein Problem bietet sich eigentlich der dynamic an damit du Partikel rausnehmen kannst.

numParticles sind alle? Sonst könntest du für dein spawning System erst einmal alle Partikel in den Buffer packen und nur einen Teil des Buffers zeichnen. die gestorbenen sind dann vor dem offset. Also z.B. glDrawArrays(GL_POINTS, dead, dead+alive); oder so in der Art.

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

3

10.06.2013, 16:33

Für dein Problem bietet sich eigentlich der dynamic an damit du Partikel rausnehmen kannst.
Wie kann ich denn Partikel wieder aus dem Buffer rausnehmen? Einfach mit NULL? Mh, ist mir noch nicht ganz klar geworden.
numParticles sind alle aktuell lebenden Partikel.

Ich verstehe einfach nicht warum der Buffer nurnoch die Häfte der Daten aufnehmen kann 8| ?(

Noch was anderes wo ich grad dabei bin: Sollten point sprites (gibts die noch in >=OGL 4?) oder ein geometry shader effizienter sein für textured billboards?

Grüße

Werbeanzeige