Skip to content

Commit dd9a4b4

Browse files
committed
Use Mesh class in Custom Shape effect
1 parent 4e9fe28 commit dd9a4b4

File tree

2 files changed

+61
-129
lines changed

2 files changed

+61
-129
lines changed

src/libprojectM/MilkdropPreset/CustomShape.cpp

Lines changed: 55 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -3,75 +3,27 @@
33
#include "PresetFileParser.hpp"
44

55
#include <Renderer/TextureManager.hpp>
6-
#include <Renderer/RenderItem.hpp>
76

87
#include <vector>
98

109
namespace libprojectM {
1110
namespace MilkdropPreset {
1211

1312
CustomShape::CustomShape(PresetState& presetState)
14-
: m_presetState(presetState)
13+
: m_outlineMesh(Renderer::VertexBufferUsage::StreamDraw)
14+
, m_fillMesh(Renderer::VertexBufferUsage::StreamDraw, true, false)
15+
, m_presetState(presetState)
1516
, m_perFrameContext(presetState.globalMemory, &presetState.globalRegisters)
1617
{
17-
std::vector<TexturedPoint> vertexData;
18-
vertexData.resize(102);
18+
m_outlineMesh.SetVertexCount(100);
19+
m_outlineMesh.SetRenderPrimitiveType(Renderer::Mesh::PrimitiveType::LineLoop);
1920

20-
glGenVertexArrays(1, &m_vaoIdTextured);
21-
glGenBuffers(1, &m_vboIdTextured);
22-
23-
glGenVertexArrays(1, &m_vaoIdUntextured);
24-
glGenBuffers(1, &m_vboIdUntextured);
25-
26-
glBindVertexArray(m_vaoIdTextured);
27-
glBindBuffer(GL_ARRAY_BUFFER, m_vboIdTextured);
28-
29-
glEnableVertexAttribArray(0);
30-
glEnableVertexAttribArray(1);
31-
glEnableVertexAttribArray(2);
32-
33-
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedPoint), reinterpret_cast<void*>(offsetof(TexturedPoint, x))); // Position
34-
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(TexturedPoint), reinterpret_cast<void*>(offsetof(TexturedPoint, r))); // Color
35-
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedPoint), reinterpret_cast<void*>(offsetof(TexturedPoint, u))); // Texture coordinate
36-
37-
glBufferData(GL_ARRAY_BUFFER, sizeof(TexturedPoint) * vertexData.size(), vertexData.data(), GL_STREAM_DRAW);
38-
39-
glBindVertexArray(m_vaoIdUntextured);
40-
glBindBuffer(GL_ARRAY_BUFFER, m_vboIdUntextured);
41-
42-
glEnableVertexAttribArray(0);
43-
glEnableVertexAttribArray(1);
44-
45-
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedPoint), reinterpret_cast<void*>(offsetof(TexturedPoint, x))); // Position
46-
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(TexturedPoint), reinterpret_cast<void*>(offsetof(TexturedPoint, r))); // Color
47-
48-
glBufferData(GL_ARRAY_BUFFER, sizeof(TexturedPoint) * vertexData.size(), vertexData.data(), GL_STREAM_DRAW);
49-
50-
RenderItem::Init();
21+
m_fillMesh.SetVertexCount(102);
22+
m_fillMesh.SetRenderPrimitiveType(Renderer::Mesh::PrimitiveType::TriangleFan);
5123

5224
m_perFrameContext.RegisterBuiltinVariables();
5325
}
5426

55-
CustomShape::~CustomShape()
56-
{
57-
glDeleteBuffers(1, &m_vboIdTextured);
58-
glDeleteVertexArrays(1, &m_vaoIdTextured);
59-
60-
glDeleteBuffers(1, &m_vboIdUntextured);
61-
glDeleteVertexArrays(1, &m_vaoIdUntextured);
62-
}
63-
64-
void CustomShape::InitVertexAttrib()
65-
{
66-
glEnableVertexAttribArray(0);
67-
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr); // points
68-
glDisableVertexAttribArray(1);
69-
70-
std::vector<Point> vertexData;
71-
vertexData.resize(100);
72-
glBufferData(GL_ARRAY_BUFFER, sizeof(Point) * vertexData.size(), vertexData.data(), GL_STREAM_DRAW);
73-
}
74-
7527
void CustomShape::Initialize(::libprojectM::PresetFileParser& parsedFile, int index)
7628
{
7729
std::string const shapecodePrefix = "shapecode_" + std::to_string(index) + "_";
@@ -148,49 +100,47 @@ void CustomShape::Draw()
148100
// Additive Drawing or Overwrite
149101
glBlendFunc(GL_SRC_ALPHA, static_cast<int>(*m_perFrameContext.additive) != 0 ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);
150102

151-
std::vector<TexturedPoint> vertexData(sides + 2);
152-
153-
vertexData[0].x = static_cast<float>(*m_perFrameContext.x * 2.0 - 1.0);
154-
vertexData[0].y = static_cast<float>(*m_perFrameContext.y * -2.0 + 1.0);
103+
auto& vertexData = m_fillMesh.Vertices();
104+
auto& colorData = m_fillMesh.Colors();
155105

156-
vertexData[0].u = 0.5f;
157-
vertexData[0].v = 0.5f;
106+
vertexData[0] = Renderer::Point(static_cast<float>(*m_perFrameContext.x * 2.0 - 1.0),
107+
static_cast<float>(*m_perFrameContext.y * -2.0 + 1.0));
158108

159109
// x = f*255.0 & 0xFF = (f*255.0) % 256
160110
// f' = x/255.0 = f % (256/255)
161111
// 1.0 -> 255 (0xFF)
162112
// 2.0 -> 254 (0xFE)
163113
// -1.0 -> 0x01
164114

165-
vertexData[0].r = Renderer::color_modulo(*m_perFrameContext.r);
166-
vertexData[0].g = Renderer::color_modulo(*m_perFrameContext.g);
167-
vertexData[0].b = Renderer::color_modulo(*m_perFrameContext.b);
168-
vertexData[0].a = Renderer::color_modulo(*m_perFrameContext.a);
115+
colorData[0] = Renderer::Color::Modulo(Renderer::Color(static_cast<float>(*m_perFrameContext.r),
116+
static_cast<float>(*m_perFrameContext.g),
117+
static_cast<float>(*m_perFrameContext.b),
118+
static_cast<float>(*m_perFrameContext.a)));
169119

170-
vertexData[1].r = Renderer::color_modulo(*m_perFrameContext.r2);
171-
vertexData[1].g = Renderer::color_modulo(*m_perFrameContext.g2);
172-
vertexData[1].b = Renderer::color_modulo(*m_perFrameContext.b2);
173-
vertexData[1].a = Renderer::color_modulo(*m_perFrameContext.a2);
120+
colorData[1] = Renderer::Color::Modulo(Renderer::Color(static_cast<float>(*m_perFrameContext.r2),
121+
static_cast<float>(*m_perFrameContext.g2),
122+
static_cast<float>(*m_perFrameContext.b2),
123+
static_cast<float>(*m_perFrameContext.a2)));
174124

175125
for (int i = 1; i < sides + 1; i++)
176126
{
177127
const float cornerProgress = static_cast<float>(i - 1) / static_cast<float>(sides);
178128
const float angle = cornerProgress * pi * 2.0f + static_cast<float>(*m_perFrameContext.ang) + pi * 0.25f;
179129

180130
// Todo: There's still some issue with aspect ratio here, as everything gets squashed horizontally if Y > x.
181-
vertexData[i].x = vertexData[0].x + static_cast<float>(*m_perFrameContext.rad) * cosf(angle) * m_presetState.renderContext.aspectY;
182-
vertexData[i].y = vertexData[0].y + static_cast<float>(*m_perFrameContext.rad) * sinf(angle);
131+
vertexData[i] = Renderer::Point(vertexData[0].X() + static_cast<float>(*m_perFrameContext.rad) * cosf(angle) * m_presetState.renderContext.aspectY,
132+
vertexData[0].Y() + static_cast<float>(*m_perFrameContext.rad) * sinf(angle));
183133

184-
vertexData[i].r = vertexData[1].r;
185-
vertexData[i].g = vertexData[1].g;
186-
vertexData[i].b = vertexData[1].b;
187-
vertexData[i].a = vertexData[1].a;
134+
colorData[i] = colorData[1];
188135
}
189136

190137
// Duplicate last vertex.
191138
vertexData[sides + 1] = vertexData[1];
139+
colorData[sides + 1] = colorData[1];
192140

193-
if (static_cast<int>(*m_perFrameContext.textured) != 0)
141+
m_fillMesh.SetUseUV(static_cast<int>(*m_perFrameContext.textured) != 0);
142+
143+
if (m_fillMesh.UseUV())
194144
{
195145
auto shader = m_presetState.texturedShader.lock();
196146
shader->Bind();
@@ -223,58 +173,55 @@ void CustomShape::Draw()
223173
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
224174
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
225175

176+
auto& uvs = m_fillMesh.UVs();
177+
178+
uvs[0] = Renderer::TextureUV(0.5f, 0.5f);
179+
226180
for (int i = 1; i < sides + 1; i++)
227181
{
228182
const float cornerProgress = static_cast<float>(i - 1) / static_cast<float>(sides);
229183
const float angle = cornerProgress * pi * 2.0f + static_cast<float>(*m_perFrameContext.tex_ang) + pi * 0.25f;
230184

231-
vertexData[i].u = 0.5f + 0.5f * cosf(angle) / static_cast<float>(*m_perFrameContext.tex_zoom) * textureAspectY;
232-
vertexData[i].v = 1.0f - (0.5f - 0.5f * sinf(angle) / static_cast<float>(*m_perFrameContext.tex_zoom)); // Vertical flip required!
185+
uvs[i] = Renderer::TextureUV(0.5f + 0.5f * cosf(angle) / static_cast<float>(*m_perFrameContext.tex_zoom) * textureAspectY,
186+
1.0f - (0.5f - 0.5f * sinf(angle) / static_cast<float>(*m_perFrameContext.tex_zoom))); // Vertical flip required!
233187
}
234188

235-
vertexData[sides + 1] = vertexData[1];
236-
237-
glBindBuffer(GL_ARRAY_BUFFER, m_vboIdTextured);
238-
239-
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(TexturedPoint) * (sides + 2), vertexData.data());
240-
241-
glBindVertexArray(m_vaoIdTextured);
242-
glDrawArrays(GL_TRIANGLE_FAN, 0, sides + 2);
243-
glBindVertexArray(0);
244-
245-
glBindTexture(GL_TEXTURE_2D, 0);
246-
Renderer::Sampler::Unbind(0);
189+
uvs[sides + 1] = uvs[1];
247190
}
248191
else
249192
{
250193
// Untextured (creates a color gradient: center=r/g/b/a to border=r2/b2/g2/a2)
251-
glBindBuffer(GL_ARRAY_BUFFER, m_vboIdUntextured);
252-
253-
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(TexturedPoint) * (sides + 2), vertexData.data());
254-
255194
auto shader = m_presetState.untexturedShader.lock();
256195
shader->Bind();
257196
shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection);
258-
259-
glBindVertexArray(m_vaoIdUntextured);
260-
glDrawArrays(GL_TRIANGLE_FAN, 0, sides + 2);
261-
glBindVertexArray(0);
262197
}
263198

199+
m_fillMesh.Indices().Resize(sides + 2);
200+
m_fillMesh.Indices().MakeContinuous();
201+
m_fillMesh.Update();
202+
m_fillMesh.Draw();
203+
204+
glBindTexture(GL_TEXTURE_2D, 0);
205+
Renderer::Sampler::Unbind(0);
206+
264207
if (*m_perFrameContext.border_a > 0.0001f)
265208
{
266-
std::vector<ShapeVertex> points(sides);
209+
m_outlineMesh.Indices().Resize(sides);
210+
m_outlineMesh.Indices().MakeContinuous();
211+
212+
auto& points = m_outlineMesh.Vertices();
267213

268214
for (int i = 0; i < sides; i++)
269215
{
270-
points[i].x = vertexData[i + 1].x;
271-
points[i].y = vertexData[i + 1].y;
216+
points[i] = m_fillMesh.Vertex(i + 1);
272217
}
273218

274219
auto shader = m_presetState.untexturedShader.lock();
275220
shader->Bind();
276221
shader->SetUniformMat4x4("vertex_transformation", PresetState::orthogonalProjection);
277222

223+
m_outlineMesh.Bind();
224+
278225
glVertexAttrib4f(1,
279226
static_cast<float>(*m_perFrameContext.border_r),
280227
static_cast<float>(*m_perFrameContext.border_g),
@@ -285,9 +232,6 @@ void CustomShape::Draw()
285232
glEnable(GL_LINE_SMOOTH);
286233
#endif
287234

288-
glBindVertexArray(m_vaoID);
289-
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
290-
291235
const auto iterations = m_thickOutline ? 4 : 1;
292236

293237
// Need to use +/- 1.0 here instead of 2.0 used in Milkdrop to achieve the same rendering result.
@@ -306,40 +250,38 @@ void CustomShape::Draw()
306250
case 1:
307251
for (auto j = 0; j < sides; j++)
308252
{
309-
points[j].x += incrementX;
253+
points[j].SetX(points[j].X() + incrementX);
310254
}
311255
break;
312256

313257
case 2:
314258
for (auto j = 0; j < sides; j++)
315259
{
316-
points[j].y += incrementY;
260+
points[j].SetY(points[j].Y() + incrementY);
317261
}
318262
break;
319263

320264
case 3:
321265
for (auto j = 0; j < sides; j++)
322266
{
323-
points[j].x -= incrementX;
267+
points[j].SetX(points[j].X() - incrementX);
324268
}
325269
break;
326270
}
327271

328-
glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizei>(sizeof(Point) * sides), points.data());
329-
glDrawArrays(GL_LINE_LOOP, 0, sides);
272+
m_outlineMesh.Update();
273+
m_outlineMesh.Draw();
330274
}
331275
}
332276
}
333277

334-
glBindBuffer(GL_ARRAY_BUFFER, 0);
335-
glBindVertexArray(0);
278+
Renderer::Mesh::Unbind();
279+
Renderer::Shader::Unbind();
336280

337281
#ifndef USE_GLES
338282
glDisable(GL_LINE_SMOOTH);
339283
#endif
340284
glDisable(GL_BLEND);
341-
342-
Renderer::Shader::Unbind();
343285
}
344286

345287
} // namespace MilkdropPreset

src/libprojectM/MilkdropPreset/CustomShape.hpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "PresetState.hpp"
55
#include "ShapePerFrameContext.hpp"
66

7-
#include <Renderer/RenderItem.hpp>
7+
#include <Renderer/Mesh.hpp>
88

99
#include <projectm-eval.h>
1010

@@ -19,14 +19,12 @@ class PresetFileParser;
1919
* The class creates two sets of VBO/VAO as it's only known later (in the Draw() call) whether the shape is textured
2020
* or not.
2121
*/
22-
class CustomShape : public Renderer::RenderItem
22+
class CustomShape
2323
{
2424
public:
2525
CustomShape(PresetState& presetState);
2626

27-
~CustomShape() override;
28-
29-
void InitVertexAttrib() override;
27+
virtual ~CustomShape() = default;
3028

3129
/**
3230
* @brief Loads the initial values and code from the preset file.
@@ -47,12 +45,10 @@ class CustomShape : public Renderer::RenderItem
4745
void Draw();
4846

4947
private:
50-
struct ShapeVertex {
51-
float x{.0f}; //!< The vertex X coordinate.
52-
float y{.0f}; //!< The vertex Y coordinate.
53-
};
48+
Renderer::Mesh m_outlineMesh; //!< The shape's border/outline mesh.
49+
Renderer::Mesh m_fillMesh; //!< The shape's color/texture mesh.
5450

55-
std::string m_image; //!< Texture filename to be rendered on this shape
51+
std::string m_image; //!< Texture filename to be rendered on this shape.
5652

5753
int m_index{0}; //!< The custom shape index in the preset.
5854
bool m_enabled{false}; //!< If false, the shape isn't drawn.
@@ -93,12 +89,6 @@ class CustomShape : public Renderer::RenderItem
9389
PresetState& m_presetState; //!< The global preset state.
9490
ShapePerFrameContext m_perFrameContext;
9591

96-
GLuint m_vboIdTextured{0}; //!< Vertex buffer object ID for a textured shape.
97-
GLuint m_vaoIdTextured{0}; //!< Vertex array object ID for a textured shape.
98-
99-
GLuint m_vboIdUntextured{0}; //!< Vertex buffer object ID for an untextured shape.
100-
GLuint m_vaoIdUntextured{0}; //!< Vertex array object ID for an untextured shape.
101-
10292
friend class ShapePerFrameContext;
10393
};
10494

0 commit comments

Comments
 (0)