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?