Skip to content

Commit 2d5a365

Browse files
committed
Use Mesh class in User Sprites
1 parent a2fac19 commit 2d5a365

File tree

4 files changed

+71
-89
lines changed

4 files changed

+71
-89
lines changed

src/libprojectM/UserSprites/MilkdropSprite.cpp

Lines changed: 32 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "UserSprites/MilkdropSprite.hpp"
22

3+
#include "SpriteException.hpp"
34
#include "SpriteShaders.hpp"
45

56
#include <Preset.hpp>
@@ -24,19 +25,9 @@ namespace libprojectM {
2425
namespace UserSprites {
2526

2627
MilkdropSprite::MilkdropSprite()
28+
: m_mesh(Renderer::VertexBufferUsage::DynamicDraw, false, true)
2729
{
28-
RenderItem::Init();
29-
}
30-
31-
void MilkdropSprite::InitVertexAttrib()
32-
{
33-
glEnableVertexAttribArray(0);
34-
glDisableVertexAttribArray(1);
35-
glEnableVertexAttribArray(2);
36-
37-
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedPoint), reinterpret_cast<void*>(offsetof(TexturedPoint, x))); // Position
38-
// Color (index 1) is passed as a 4-float constant vertex attribute.
39-
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedPoint), reinterpret_cast<void*>(offsetof(TexturedPoint, u))); // Texture coordinate
30+
m_mesh.SetVertexCount(4);
4031
}
4132

4233
void MilkdropSprite::Init(const std::string& spriteData, const Renderer::RenderContext& renderContext)
@@ -119,7 +110,7 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
119110
m_spriteDone = *m_codeContext.done != 0.0;
120111
bool burnIn = *m_codeContext.burn != 0.0;
121112

122-
Quad vertices{};
113+
auto& vertices = m_mesh.Vertices().Get();
123114

124115
// Get values from expression code and clamp them where necessary.
125116
float x = std::min(1000.0f, std::max(-1000.0f, static_cast<float>(*m_codeContext.x) * 2.0f - 1.0f));
@@ -139,14 +130,14 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
139130
float a = std::min(1.0f, std::max(0.0f, (static_cast<float>(*m_codeContext.a))));
140131

141132
// ToDo: Move all translations to vertex shader
142-
vertices[0 + flipx].x = -sx;
143-
vertices[1 - flipx].x = sx;
144-
vertices[2 + flipx].x = -sx;
145-
vertices[3 - flipx].x = sx;
146-
vertices[0 + flipy * 2].y = -sy;
147-
vertices[1 + flipy * 2].y = -sy;
148-
vertices[2 - flipy * 2].y = sy;
149-
vertices[3 - flipy * 2].y = sy;
133+
vertices[0 + flipx].SetX(-sx);
134+
vertices[1 - flipx].SetX(sx);
135+
vertices[2 + flipx].SetX(-sx);
136+
vertices[3 - flipx].SetX(sx);
137+
vertices[0 + flipy * 2].SetY(-sy);
138+
vertices[1 + flipy * 2].SetY(-sy);
139+
vertices[2 - flipy * 2].SetY(sy);
140+
vertices[3 - flipy * 2].SetY(sy);
150141

151142
// First aspect ratio: adjust for non-1:1 images
152143
{
@@ -157,15 +148,15 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
157148
// Landscape image
158149
for (auto& vertex : vertices)
159150
{
160-
vertex.y *= aspect;
151+
vertex.SetY(vertex.Y() * aspect);
161152
}
162153
}
163154
else
164155
{
165156
// Portrait image
166157
for (auto& vertex : vertices)
167158
{
168-
vertex.x /= aspect;
159+
vertex.SetX(vertex.X() / aspect);
169160
}
170161
}
171162
}
@@ -177,18 +168,17 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
177168

178169
for (auto& vertex : vertices)
179170
{
180-
float rotX = vertex.x * cos_rot - vertex.y * sin_rot;
181-
float rotY = vertex.x * sin_rot + vertex.y * cos_rot;
182-
vertex.x = rotX;
183-
vertex.y = rotY;
171+
float rotX = vertex.X() * cos_rot - vertex.Y() * sin_rot;
172+
float rotY = vertex.X() * sin_rot + vertex.Y() * cos_rot;
173+
vertex = {rotX, rotY};
184174
}
185175
}
186176

187177
// Translation
188178
for (auto& vertex : vertices)
189179
{
190-
vertex.x += x;
191-
vertex.y += y;
180+
vertex.SetX(vertex.X() + x);
181+
vertex.SetY(vertex.Y() + y);
192182
}
193183

194184
// Second aspect ratio: normalize to width of screen
@@ -199,14 +189,14 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
199189
{
200190
for (auto& vertex : vertices)
201191
{
202-
vertex.y *= aspect;
192+
vertex.SetY(vertex.Y() * aspect);
203193
}
204194
}
205195
else
206196
{
207197
for (auto& vertex : vertices)
208198
{
209-
vertex.x /= aspect;
199+
vertex.SetX(vertex.X() / aspect);
210200
}
211201
}
212202
}
@@ -219,19 +209,15 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
219209
float dtu = 0.5f;
220210
float dtv = 0.5f;
221211

222-
vertices[0].u = -dtu;
223-
vertices[1].u = dtu;
224-
vertices[2].u = -dtu;
225-
vertices[3].u = dtu;
226-
vertices[0].v = -dtv;
227-
vertices[1].v = -dtv;
228-
vertices[2].v = dtv;
229-
vertices[3].v = dtv;
212+
m_mesh.UVs().Set({{-dtu, -dtv},
213+
{dtu, -dtv},
214+
{-dtu, dtv},
215+
{dtu, dtv}});
230216

231-
for (auto& vertex : vertices)
217+
for (auto& uv : m_mesh.UVs().Get())
232218
{
233-
vertex.u = (vertex.u - 0.0f) * repeatx + 0.5f;
234-
vertex.v = (vertex.v - 0.0f) * repeaty + 0.5f;
219+
uv = {(uv.U() - 0.0f) * repeatx + 0.5f,
220+
(uv.V() - 0.0f) * repeaty + 0.5f};
235221
}
236222
}
237223

@@ -243,9 +229,7 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
243229
m_texture->Bind(0);
244230
m_sampler.Bind(0);
245231

246-
glBindVertexArray(m_vaoID);
247-
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
248-
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_DYNAMIC_DRAW);
232+
m_mesh.Update();
249233

250234
glVertexAttrib4f(1, r, g, b, a);
251235

@@ -275,7 +259,7 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
275259
}
276260

277261
// Draw to current output buffer
278-
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
262+
m_mesh.Draw();
279263

280264
if (burnIn)
281265
{
@@ -288,7 +272,7 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
288272
}
289273

290274
preset.get()->BindFramebuffer();
291-
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
275+
m_mesh.Draw();
292276
}
293277

294278
// Reset to original FBO
@@ -300,6 +284,7 @@ void MilkdropSprite::Draw(const Audio::FrameAudioData& audioData,
300284
glBindBuffer(GL_ARRAY_BUFFER, 0);
301285
glBindVertexArray(0);
302286
m_texture->Unbind(0);
287+
Renderer::Mesh::Unbind();
303288
Renderer::Shader::Unbind();
304289
}
305290

src/libprojectM/UserSprites/MilkdropSprite.hpp

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "UserSprites/Sprite.hpp"
44

5+
#include <Renderer/Mesh.hpp>
56
#include <Renderer/Texture.hpp>
67
#include <Renderer/TextureSamplerDescriptor.hpp>
78

@@ -17,25 +18,20 @@ class MilkdropSprite : public Sprite
1718

1819
~MilkdropSprite() override = default;
1920

20-
void InitVertexAttrib() override;
21-
2221
void Init(const std::string& spriteData, const Renderer::RenderContext& renderContext) override;
2322

2423
void Draw(const Audio::FrameAudioData& audioData,
2524
const Renderer::RenderContext& renderContext,
2625
uint32_t outputFramebufferObject,
2726
PresetList presets) override;
2827

29-
auto Done() const-> bool override;
28+
auto Done() const -> bool override;
3029

3130
private:
32-
using Quad = std::array<TexturedPoint, 4>;
33-
3431
/**
3532
* @brief Context for the init and per-frame code.
3633
*/
37-
struct CodeContext
38-
{
34+
struct CodeContext {
3935
CodeContext();
4036

4137
~CodeContext();
@@ -61,46 +57,45 @@ class MilkdropSprite : public Sprite
6157
const Renderer::RenderContext& renderContext);
6258

6359
projectm_eval_context* spriteCodeContext{nullptr}; //!< The code runtime context, holds memory buffers and variables.
64-
projectm_eval_code* perFrameCodeHandle{nullptr}; //!< The compiled per-frame code handle.
60+
projectm_eval_code* perFrameCodeHandle{nullptr}; //!< The compiled per-frame code handle.
6561

6662
// Input variables
67-
PRJM_EVAL_F* time{}; //!< Time passed since program start. Also available in init code.
68-
PRJM_EVAL_F* frame{}; //!< Total frames rendered so far. Also available in init code.
69-
PRJM_EVAL_F* fps{}; //!< Current (or, if not available, target) frames per second value.
63+
PRJM_EVAL_F* time{}; //!< Time passed since program start. Also available in init code.
64+
PRJM_EVAL_F* frame{}; //!< Total frames rendered so far. Also available in init code.
65+
PRJM_EVAL_F* fps{}; //!< Current (or, if not available, target) frames per second value.
7066
PRJM_EVAL_F* progress{}; //!< Preset blending progress (only if blending).
71-
PRJM_EVAL_F* bass{}; //!< Bass frequency loudness, median of 1.0, range of ~0.7 to ~1.3 in most cases.
72-
PRJM_EVAL_F* mid{}; //!< Middle frequency loudness, median of 1.0, range of ~0.7 to ~1.3 in most cases.
73-
PRJM_EVAL_F* treb{}; //!< Treble frequency loudness, median of 1.0, range of ~0.7 to ~1.3 in most cases.
67+
PRJM_EVAL_F* bass{}; //!< Bass frequency loudness, median of 1.0, range of ~0.7 to ~1.3 in most cases.
68+
PRJM_EVAL_F* mid{}; //!< Middle frequency loudness, median of 1.0, range of ~0.7 to ~1.3 in most cases.
69+
PRJM_EVAL_F* treb{}; //!< Treble frequency loudness, median of 1.0, range of ~0.7 to ~1.3 in most cases.
7470
PRJM_EVAL_F* bass_att{}; //!< More attenuated/smoothed value of bass.
75-
PRJM_EVAL_F* mid_att{}; //!< More attenuated/smoothed value of mid.
71+
PRJM_EVAL_F* mid_att{}; //!< More attenuated/smoothed value of mid.
7672
PRJM_EVAL_F* treb_att{}; //!< More attenuated/smoothed value of treb.
7773

7874
// Output variables
79-
PRJM_EVAL_F* done{}; //!< If this becomes non-zero, the sprite is deleted. Default: 0.0
80-
PRJM_EVAL_F* burn{}; //!< If non-zero, the sprite will be "burned" into currently rendered presets when done is also true, effectively "dissolving" the sprite in the preset. Default: 1.0
81-
PRJM_EVAL_F* x{}; //!< Sprite x position (position of the image center). Range from -1000 to 1000. Default: 0.5
82-
PRJM_EVAL_F* y{}; //!< Sprite y position (position of the image center). Range from -1000 to 1000. Default: 0.5
83-
PRJM_EVAL_F* sx{}; //!< Sprite x scaling factor. Range from -1000 to 1000. Default: 1.0
84-
PRJM_EVAL_F* sy{}; //!< Sprite y scaling factor. Range from -1000 to 1000. Default: 1.0
85-
PRJM_EVAL_F* rot{}; //!< Sprite rotation in radians (2*PI equals one full rotation). Default: 0.0
86-
PRJM_EVAL_F* flipx{}; //!< If flag is non-zero, the sprite is flipped on the x axis. Default: 0.0
87-
PRJM_EVAL_F* flipy{}; //!< If flag is non-zero, the sprite is flipped on the y axis. Default: 0.0
88-
PRJM_EVAL_F* repeatx{}; //!< Repeat count of the image on the sprite quad on the x axis. Fractional values allowed. Range from 0.01 to 100.0. Default: 1.0
89-
PRJM_EVAL_F* repeaty{}; //!< Repeat count of the image on the sprite quad on the y axis. Fractional values allowed. Range from 0.01 to 100.0. Default: 1.0
75+
PRJM_EVAL_F* done{}; //!< If this becomes non-zero, the sprite is deleted. Default: 0.0
76+
PRJM_EVAL_F* burn{}; //!< If non-zero, the sprite will be "burned" into currently rendered presets when done is also true, effectively "dissolving" the sprite in the preset. Default: 1.0
77+
PRJM_EVAL_F* x{}; //!< Sprite x position (position of the image center). Range from -1000 to 1000. Default: 0.5
78+
PRJM_EVAL_F* y{}; //!< Sprite y position (position of the image center). Range from -1000 to 1000. Default: 0.5
79+
PRJM_EVAL_F* sx{}; //!< Sprite x scaling factor. Range from -1000 to 1000. Default: 1.0
80+
PRJM_EVAL_F* sy{}; //!< Sprite y scaling factor. Range from -1000 to 1000. Default: 1.0
81+
PRJM_EVAL_F* rot{}; //!< Sprite rotation in radians (2*PI equals one full rotation). Default: 0.0
82+
PRJM_EVAL_F* flipx{}; //!< If flag is non-zero, the sprite is flipped on the x axis. Default: 0.0
83+
PRJM_EVAL_F* flipy{}; //!< If flag is non-zero, the sprite is flipped on the y axis. Default: 0.0
84+
PRJM_EVAL_F* repeatx{}; //!< Repeat count of the image on the sprite quad on the x axis. Fractional values allowed. Range from 0.01 to 100.0. Default: 1.0
85+
PRJM_EVAL_F* repeaty{}; //!< Repeat count of the image on the sprite quad on the y axis. Fractional values allowed. Range from 0.01 to 100.0. Default: 1.0
9086
PRJM_EVAL_F* blendmode{}; //!< Image blending mode. 0 = Alpha blending (default), 1 = Decal mode (no transparency), 2 = Additive blending, 3 = Source color blending, 4 = Color key blending. Default: 0
91-
PRJM_EVAL_F* r{}; //!< Modulation color used in some blending modes. Default: 1.0
92-
PRJM_EVAL_F* g{}; //!< Modulation color used in some blending modes. Default: 1.0
93-
PRJM_EVAL_F* b{}; //!< Modulation color used in some blending modes. Default: 1.0
94-
PRJM_EVAL_F* a{}; //!< Modulation color used in some blending modes. Default: 1.0
95-
87+
PRJM_EVAL_F* r{}; //!< Modulation color used in some blending modes. Default: 1.0
88+
PRJM_EVAL_F* g{}; //!< Modulation color used in some blending modes. Default: 1.0
89+
PRJM_EVAL_F* b{}; //!< Modulation color used in some blending modes. Default: 1.0
90+
PRJM_EVAL_F* a{}; //!< Modulation color used in some blending modes. Default: 1.0
9691
};
9792

98-
CodeContext m_codeContext; //!< Sprite init and per-frame code.
99-
std::shared_ptr<Renderer::Texture> m_texture; //!< The sprite image, loaded via a name like other textures in Milkdrop presets.
93+
CodeContext m_codeContext; //!< Sprite init and per-frame code.
94+
std::shared_ptr<Renderer::Texture> m_texture; //!< The sprite image, loaded via a name like other textures in Milkdrop presets.
10095
Renderer::Sampler m_sampler{GL_REPEAT, GL_LINEAR}; //!< Texture sampler settings
101-
std::weak_ptr<Renderer::Shader> m_spriteShader; //!< The shader used to draw the user sprite.
102-
bool m_spriteDone{false}; //!< If true, the sprite will be removed from the list.
103-
96+
std::weak_ptr<Renderer::Shader> m_spriteShader; //!< The shader used to draw the user sprite.
97+
Renderer::Mesh m_mesh; //!< A simple quad.
98+
bool m_spriteDone{false}; //!< If true, the sprite will be removed from the list.
10499
};
105100

106101
} // namespace UserSprites

src/libprojectM/UserSprites/Sprite.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
#pragma once
22

3-
#include "UserSprites/SpriteException.hpp"
4-
53
#include <Preset.hpp>
64

75
#include <Audio/FrameAudioData.hpp>
86

97
#include <Renderer/RenderContext.hpp>
10-
#include <Renderer/RenderItem.hpp>
118

129
#include <cstdint>
1310
#include <functional>
@@ -18,12 +15,14 @@
1815
namespace libprojectM {
1916
namespace UserSprites {
2017

21-
class Sprite : public Renderer::RenderItem
18+
class Sprite
2219
{
2320
public:
2421
using Ptr = std::unique_ptr<Sprite>;
2522
using PresetList = std::vector<std::reference_wrapper<const std::unique_ptr<Preset>>>;
2623

24+
virtual ~Sprite() = default;
25+
2726
/**
2827
* @brief Initializes the sprite instance for rendering.
2928
* @param spriteData The data for the sprite type.

src/libprojectM/UserSprites/SpriteManager.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "UserSprites/SpriteManager.hpp"
22

33
#include "UserSprites/Factory.hpp"
4+
#include "UserSprites/SpriteException.hpp"
45

56
#include <Renderer/Shader.hpp>
67

@@ -62,7 +63,8 @@ void SpriteManager::Draw(const Audio::FrameAudioData& audioData,
6263
uint32_t outputFramebufferObject,
6364
Sprite::PresetList presets)
6465
{
65-
for (auto& idAndSprite : m_sprites) {
66+
for (auto& idAndSprite : m_sprites)
67+
{
6668
idAndSprite.second->Draw(audioData, renderContext, outputFramebufferObject, presets);
6769

6870
if (idAndSprite.second->Done())
@@ -99,7 +101,8 @@ auto SpriteManager::ActiveSpriteCount() const -> uint32_t
99101
auto SpriteManager::ActiveSpriteIdentifiers() const -> std::vector<SpriteIdentifier>
100102
{
101103
std::vector<SpriteIdentifier> identifierList;
102-
for (auto& idAndSprite : m_sprites) {
104+
for (auto& idAndSprite : m_sprites)
105+
{
103106
identifierList.emplace_back(idAndSprite.first);
104107
}
105108

0 commit comments

Comments
 (0)