1818namespace libprojectM {
1919namespace MilkdropPreset {
2020
21- static constexpr uint32_t VerticesPerDrawCall = 1024 * 3 ;
22-
2321PerPixelMesh::PerPixelMesh ()
24- : RenderItem()
25- {
26- RenderItem::Init ();
27- }
28-
29- void PerPixelMesh::InitVertexAttrib ()
22+ : m_warpMesh(Renderer::VertexBufferUsage::StreamDraw)
3023{
31- m_drawVertices.resize (VerticesPerDrawCall); // Fixed size, may scale it later depending on GPU caps.
32-
33- glGenVertexArrays (1 , &m_vaoID);
34- glGenBuffers (1 , &m_vboID);
35-
36- glBindVertexArray (m_vaoID);
37- glBindBuffer (GL_ARRAY_BUFFER, m_vboID);
38-
39- glEnableVertexAttribArray (0 );
40- glEnableVertexAttribArray (1 );
41- glEnableVertexAttribArray (2 );
42- glEnableVertexAttribArray (3 );
43- glEnableVertexAttribArray (4 );
44- glEnableVertexAttribArray (5 );
45-
46- // Only position & texture coordinates are per-vertex, colors are equal all over the grid (used for decay).
47- glVertexAttribPointer (0 , 2 , GL_FLOAT, GL_FALSE, sizeof (MeshVertex), reinterpret_cast <void *>(offsetof (MeshVertex, x))); // Position, radius & angle
48- glVertexAttribPointer (1 , 2 , GL_FLOAT, GL_FALSE, sizeof (MeshVertex), reinterpret_cast <void *>(offsetof (MeshVertex, radius))); // Position, radius & angle
49- glVertexAttribPointer (2 , 4 , GL_FLOAT, GL_FALSE, sizeof (MeshVertex), reinterpret_cast <void *>(offsetof (MeshVertex, zoom))); // zoom, zoom exponent, rotation & warp
50- glVertexAttribPointer (3 , 2 , GL_FLOAT, GL_FALSE, sizeof (MeshVertex), reinterpret_cast <void *>(offsetof (MeshVertex, centerX))); // Center coord
51- glVertexAttribPointer (4 , 2 , GL_FLOAT, GL_FALSE, sizeof (MeshVertex), reinterpret_cast <void *>(offsetof (MeshVertex, distanceX))); // Distance
52- glVertexAttribPointer (5 , 2 , GL_FLOAT, GL_FALSE, sizeof (MeshVertex), reinterpret_cast <void *>(offsetof (MeshVertex, stretchX))); // Stretch
53-
54- // Pre-allocate vertex buffer
55- glBufferData (GL_ARRAY_BUFFER, sizeof (MeshVertex) * m_drawVertices.size (), m_drawVertices.data (), GL_STREAM_DRAW);
56-
57- glBindVertexArray (0 );
58- glBindBuffer (GL_ARRAY_BUFFER, 0 );
24+ m_warpMesh.SetRenderPrimitiveType (Renderer::Mesh::PrimitiveType::Triangles);
25+
26+ m_warpMesh.Bind ();
27+ m_radiusAngleBuffer.Bind ();
28+ m_zoomRotWarpBuffer.Bind ();
29+ m_centerBuffer.Bind ();
30+ m_distanceBuffer.Bind ();
31+ m_stretchBuffer.Bind ();
32+
33+ m_radiusAngleBuffer.InitializeAttributePointer (3 );
34+ m_zoomRotWarpBuffer.InitializeAttributePointer (4 );
35+ m_centerBuffer.InitializeAttributePointer (5 );
36+ m_distanceBuffer.InitializeAttributePointer (6 );
37+ m_stretchBuffer.InitializeAttributePointer (7 );
38+
39+ Renderer::VertexBuffer<Renderer::Point>::SetEnableAttributeArray (3 , true );
40+ Renderer::VertexBuffer<Renderer::Point>::SetEnableAttributeArray (4 , true );
41+ Renderer::VertexBuffer<Renderer::Point>::SetEnableAttributeArray (5 , true );
42+ Renderer::VertexBuffer<Renderer::Point>::SetEnableAttributeArray (6 , true );
43+ Renderer::VertexBuffer<Renderer::Point>::SetEnableAttributeArray (7 , true );
44+
45+ Renderer::Mesh::Unbind ();
5946}
6047
6148void PerPixelMesh::LoadWarpShader (const PresetState& presetState)
@@ -139,9 +126,17 @@ void PerPixelMesh::InitializeMesh(const PresetState& presetState)
139126 m_gridSizeX = presetState.renderContext .perPixelMeshX ;
140127 m_gridSizeY = presetState.renderContext .perPixelMeshY ;
141128
142- // Grid size has changed, reallocate vertex buffers
143- m_vertices.resize ((m_gridSizeX + 1 ) * (m_gridSizeY + 1 ));
144- m_listIndices.resize (m_gridSizeX * m_gridSizeY * 6 );
129+ // Grid size has changed, resize buffers accordingly
130+ const size_t vertexCount = (m_gridSizeX + 1 ) * (m_gridSizeY + 1 );
131+
132+ m_warpMesh.SetVertexCount (vertexCount);
133+ m_radiusAngleBuffer.Resize (vertexCount);
134+ m_zoomRotWarpBuffer.Resize (vertexCount);
135+ m_centerBuffer.Resize (vertexCount);
136+ m_distanceBuffer.Resize (vertexCount);
137+ m_stretchBuffer.Resize (vertexCount);
138+
139+ m_warpMesh.Indices ().Resize (m_gridSizeX * m_gridSizeY * 6 );
145140 }
146141 else if (m_viewportWidth == presetState.renderContext .viewportSizeX &&
147142 m_viewportHeight == presetState.renderContext .viewportSizeY )
@@ -150,29 +145,29 @@ void PerPixelMesh::InitializeMesh(const PresetState& presetState)
150145 return ;
151146 }
152147
153- float aspectX = static_cast < float >( presetState.renderContext .aspectX ) ;
154- float aspectY = static_cast < float >( presetState.renderContext .aspectY ) ;
148+ const float aspectX = presetState.renderContext .aspectX ;
149+ const float aspectY = presetState.renderContext .aspectY ;
155150
156151 // Either viewport size or mesh size changed, reinitialize the vertices.
152+ auto & vertices = m_warpMesh.Vertices ();
157153 int vertexIndex{0 };
158154 for (int gridY = 0 ; gridY <= m_gridSizeY; gridY++)
159155 {
160156 for (int gridX = 0 ; gridX <= m_gridSizeX; gridX++)
161157 {
162- auto & vertex = m_vertices.at (vertexIndex);
163-
164- vertex.x = static_cast <float >(gridX) / static_cast <float >(m_gridSizeX) * 2 .0f - 1 .0f ;
165- vertex.y = static_cast <float >(gridY) / static_cast <float >(m_gridSizeY) * 2 .0f - 1 .0f ;
158+ const float x = static_cast <float >(gridX) / static_cast <float >(m_gridSizeX) * 2 .0f - 1 .0f ;
159+ const float y = static_cast <float >(gridY) / static_cast <float >(m_gridSizeY) * 2 .0f - 1 .0f ;
160+ vertices[vertexIndex] = {x, y};
166161
167162 // Milkdrop uses sqrtf, but hypotf is probably safer.
168- vertex .radius = hypotf (vertex. x * aspectX, vertex. y * aspectY);
163+ m_radiusAngleBuffer[vertexIndex] .radius = hypotf (x * aspectX, y * aspectY);
169164 if (gridY == m_gridSizeY / 2 && gridX == m_gridSizeX / 2 )
170165 {
171- vertex .angle = 0 .0f ;
166+ m_radiusAngleBuffer[vertexIndex] .angle = 0 .0f ;
172167 }
173168 else
174169 {
175- vertex .angle = atan2f (vertex. y * aspectY, vertex. x * aspectX);
170+ m_radiusAngleBuffer[vertexIndex] .angle = atan2f (y * aspectY, x * aspectX);
176171 }
177172
178173 vertexIndex++;
@@ -204,12 +199,12 @@ void PerPixelMesh::InitializeMesh(const PresetState& presetState)
204199 // 0 - 1 3
205200 // / /
206201 // 2 4 - 5
207- m_listIndices. at ( vertexListIndex++) = vertex;
208- m_listIndices. at ( vertexListIndex++) = vertex + 1 ;
209- m_listIndices. at ( vertexListIndex++) = vertex + m_gridSizeX + 1 ;
210- m_listIndices. at ( vertexListIndex++) = vertex + 1 ;
211- m_listIndices. at ( vertexListIndex++) = vertex + m_gridSizeX + 1 ;
212- m_listIndices. at ( vertexListIndex++) = vertex + m_gridSizeX + 2 ;
202+ m_warpMesh. Indices ()[ vertexListIndex++] = vertex;
203+ m_warpMesh. Indices ()[ vertexListIndex++] = vertex + 1 ;
204+ m_warpMesh. Indices ()[ vertexListIndex++] = vertex + m_gridSizeX + 1 ;
205+ m_warpMesh. Indices ()[ vertexListIndex++] = vertex + 1 ;
206+ m_warpMesh. Indices ()[ vertexListIndex++] = vertex + m_gridSizeX + 1 ;
207+ m_warpMesh. Indices ()[ vertexListIndex++] = vertex + m_gridSizeX + 2 ;
213208 }
214209 }
215210 }
@@ -232,19 +227,25 @@ void PerPixelMesh::CalculateMesh(const PresetState& presetState, const PerFrameC
232227 int vertex = 0 ;
233228
234229 // Can't make this multithreaded as per-pixel code may use gmegabuf or regXX vars.
230+ auto & vertices = m_warpMesh.Vertices ();
235231 for (int y = 0 ; y <= m_gridSizeY; y++)
236232 {
237233 for (int x = 0 ; x <= m_gridSizeX; x++)
238234 {
239- auto & curVertex = m_vertices[vertex];
235+ auto & curVertex = vertices[vertex];
236+ auto & curRadiusAngle = m_radiusAngleBuffer[vertex];
237+ auto & curZoomRotWarp = m_zoomRotWarpBuffer[vertex];
238+ auto & curCenter = m_centerBuffer[vertex];
239+ auto & curDistance = m_distanceBuffer[vertex];
240+ auto & curStretch = m_stretchBuffer[vertex];
240241
241242 // Execute per-vertex/per-pixel code if the preset uses it.
242243 if (perPixelContext.perPixelCodeHandle )
243244 {
244- *perPixelContext.x = static_cast <double >(curVertex.x * 0 .5f * presetState.renderContext .aspectX + 0 .5f );
245- *perPixelContext.y = static_cast <double >(curVertex.y * -0 .5f * presetState.renderContext .aspectY + 0 .5f );
246- *perPixelContext.rad = static_cast <double >(curVertex .radius );
247- *perPixelContext.ang = static_cast <double >(curVertex .angle );
245+ *perPixelContext.x = static_cast <double >(curVertex.X () * 0 .5f * presetState.renderContext .aspectX + 0 .5f );
246+ *perPixelContext.y = static_cast <double >(curVertex.Y () * -0 .5f * presetState.renderContext .aspectY + 0 .5f );
247+ *perPixelContext.rad = static_cast <double >(curRadiusAngle .radius );
248+ *perPixelContext.ang = static_cast <double >(curRadiusAngle .angle );
248249 *perPixelContext.zoom = static_cast <double >(*perFrameContext.zoom );
249250 *perPixelContext.zoomexp = static_cast <double >(*perFrameContext.zoomexp );
250251 *perPixelContext.rot = static_cast <double >(*perFrameContext.rot );
@@ -258,34 +259,38 @@ void PerPixelMesh::CalculateMesh(const PresetState& presetState, const PerFrameC
258259
259260 perPixelContext.ExecutePerPixelCode ();
260261
261- curVertex .zoom = static_cast <float >(*perPixelContext.zoom );
262- curVertex .zoomExp = static_cast <float >(*perPixelContext.zoomexp );
263- curVertex .rot = static_cast <float >(*perPixelContext.rot );
264- curVertex .warp = static_cast <float >(*perPixelContext.warp );
265- curVertex. centerX = static_cast <float >(*perPixelContext.cx );
266- curVertex. centerY = static_cast <float >(*perPixelContext.cy );
267- curVertex. distanceX = static_cast <float >(*perPixelContext.dx );
268- curVertex. distanceY = static_cast <float >(*perPixelContext.dy );
269- curVertex. stretchX = static_cast <float >(*perPixelContext.sx );
270- curVertex. stretchY = static_cast <float >(*perPixelContext.sy );
262+ curZoomRotWarp .zoom = static_cast <float >(*perPixelContext.zoom );
263+ curZoomRotWarp .zoomExp = static_cast <float >(*perPixelContext.zoomexp );
264+ curZoomRotWarp .rot = static_cast <float >(*perPixelContext.rot );
265+ curZoomRotWarp .warp = static_cast <float >(*perPixelContext.warp );
266+ curCenter = { static_cast <float >(*perPixelContext.cx ),
267+ static_cast <float >(*perPixelContext.cy )} ;
268+ curDistance = { static_cast <float >(*perPixelContext.dx ),
269+ static_cast <float >(*perPixelContext.dy )} ;
270+ curStretch = { static_cast <float >(*perPixelContext.sx ),
271+ static_cast <float >(*perPixelContext.sy )} ;
271272 }
272273 else
273274 {
274- curVertex.zoom = zoom;
275- curVertex.zoomExp = zoomExp;
276- curVertex.rot = rot;
277- curVertex.warp = warp;
278- curVertex.centerX = cx;
279- curVertex.centerY = cy;
280- curVertex.distanceX = dx;
281- curVertex.distanceY = dy;
282- curVertex.stretchX = sx;
283- curVertex.stretchY = sy;
275+ curZoomRotWarp.zoom = zoom;
276+ curZoomRotWarp.zoomExp = zoomExp;
277+ curZoomRotWarp.rot = rot;
278+ curZoomRotWarp.warp = warp;
279+ curCenter = { cx, cy};
280+ curDistance = {dx, dy};
281+ curStretch = {sx, sy};
284282 }
285283
286284 vertex++;
287285 }
288286 }
287+
288+ m_warpMesh.Update ();
289+ m_radiusAngleBuffer.Update ();
290+ m_zoomRotWarpBuffer.Update ();
291+ m_centerBuffer.Update ();
292+ m_distanceBuffer.Update ();
293+ m_stretchBuffer.Update ();
289294}
290295
291296void PerPixelMesh::WarpedBlit (const PresetState& presetState,
@@ -362,38 +367,9 @@ void PerPixelMesh::WarpedBlit(const PresetState& presetState,
362367 }
363368 m_perPixelSampler.Bind (0 );
364369
365- glBindVertexArray (m_vaoID);
366- glBindBuffer (GL_ARRAY_BUFFER, m_vboID);
367-
368- int trianglesPerBatch = static_cast <int >(m_drawVertices.size () / 3 - 4 );
369- int triangleCount = m_gridSizeX * m_gridSizeY * 2 ; // Two triangles per quad/grid cell.
370- int sourceIndex = 0 ;
371-
372- while (sourceIndex < triangleCount * 3 )
373- {
374- int trianglesQueued = 0 ;
375- int vertex = 0 ;
376- while (trianglesQueued < trianglesPerBatch && sourceIndex < triangleCount * 3 )
377- {
378- // Copy one triangle/3 vertices
379- for (int i = 0 ; i < 3 ; i++)
380- {
381- m_drawVertices[vertex++] = m_vertices[m_listIndices[sourceIndex++]];
382- }
383-
384- trianglesQueued++;
385- }
386-
387- if (trianglesQueued > 0 )
388- {
389- glBufferSubData (GL_ARRAY_BUFFER, 0 , sizeof (MeshVertex) * trianglesQueued * 3 , m_drawVertices.data ());
390- glDrawArrays (GL_TRIANGLES, 0 , trianglesQueued * 3 );
391- }
392- }
393-
394- glBindVertexArray (0 );
395- glBindBuffer (GL_ARRAY_BUFFER, 0 );
370+ m_warpMesh.Draw ();
396371
372+ Renderer::Mesh::Unbind ();
397373 Renderer::Sampler::Unbind (0 );
398374 Renderer::Shader::Unbind ();
399375}
0 commit comments