Skip to content

Commit 90e158d

Browse files
committed
Use Mesh class in Motion Vector effect
Also get rid of the additional index attribute array, as gl_VertexID contains the same information and is free.
1 parent 7df5dca commit 90e158d

File tree

3 files changed

+24
-72
lines changed

3 files changed

+24
-72
lines changed

src/libprojectM/MilkdropPreset/MotionVectors.cpp

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,16 @@
55
#include <Renderer/ShaderCache.hpp>
66
#include <Renderer/TextureManager.hpp>
77

8+
#include <algorithm>
9+
810
namespace libprojectM {
911
namespace MilkdropPreset {
1012

1113
MotionVectors::MotionVectors(PresetState& presetState)
12-
: RenderItem()
13-
, m_presetState(presetState)
14+
: m_presetState(presetState)
15+
, m_motionVectorMesh(Renderer::VertexBufferUsage::StreamDraw)
1416
{
15-
RenderItem::Init();
16-
}
17-
18-
void MotionVectors::InitVertexAttrib()
19-
{
20-
glEnableVertexAttribArray(0);
21-
glDisableVertexAttribArray(1);
22-
glEnableVertexAttribArray(2);
23-
24-
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(MotionVectorVertex), reinterpret_cast<void*>(offsetof(MotionVectorVertex, x)));
25-
glVertexAttribIPointer(2, 1, GL_INT, sizeof(MotionVectorVertex), reinterpret_cast<void*>(offsetof(MotionVectorVertex, index)));
17+
m_motionVectorMesh.SetRenderPrimitiveType(Renderer::Mesh::PrimitiveType::Lines);
2618
}
2719

2820
void MotionVectors::Draw(const PerFrameContext& presetPerFrameContext, std::shared_ptr<Renderer::Texture> motionTexture)
@@ -59,30 +51,16 @@ void MotionVectors::Draw(const PerFrameContext& presetPerFrameContext, std::shar
5951
auto const divertY2 = static_cast<float>(*presetPerFrameContext.mv_dy);
6052

6153
// Clamp X/Y diversions to 0..1
62-
if (divertX < 0.0f)
63-
{
64-
divertX = 0.0f;
65-
}
66-
if (divertX > 1.0f)
67-
{
68-
divertX = 1.0f;
69-
}
70-
if (divertY < 0.0f)
71-
{
72-
divertY = 0.0f;
73-
}
74-
if (divertY > 1.0f)
75-
{
76-
divertY = 1.0f;
77-
}
54+
divertX = std::min(1.0f, std::max(0.0f, divertX));
55+
divertY = std::min(1.0f, std::max(0.0f, divertY));
7856

7957
// Tweaked this a bit to ensure lines are always at least a bit more than 1px long.
8058
// Line smoothing makes some of them disappear otherwise.
8159
float const inverseWidth = 1.25f / static_cast<float>(m_presetState.renderContext.viewportSizeX);
8260
float const inverseHeight = 1.25f / static_cast<float>(m_presetState.renderContext.viewportSizeY);
8361
float const minimumLength = sqrtf(inverseWidth * inverseWidth + inverseHeight * inverseHeight);
8462

85-
std::vector<MotionVectorVertex> lineVertices(static_cast<std::size_t>(countX + 1) * 2); // countX + 1 lines for each grid row, 2 vertices each.
63+
m_motionVectorMesh.SetVertexCount(static_cast<std::size_t>(countX + 1) * 2); // countX + 1 lines for each grid row, 2 vertices each.
8664

8765
glEnable(GL_BLEND);
8866
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -103,14 +81,13 @@ void MotionVectors::Draw(const PerFrameContext& presetPerFrameContext, std::shar
10381
static_cast<float>(*presetPerFrameContext.mv_b),
10482
static_cast<float>(*presetPerFrameContext.mv_a));
10583

106-
glBindVertexArray(m_vaoID);
107-
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
108-
10984
glLineWidth(1);
11085
#ifndef USE_GLES
11186
glEnable(GL_LINE_SMOOTH);
11287
#endif
11388

89+
auto& lineVertices = m_motionVectorMesh.Vertices();
90+
11491
for (int y = 0; y < countY; y++)
11592
{
11693
float const posY = (static_cast<float>(y) + 0.25f) / (static_cast<float>(countY) + divertY + 0.25f - 1.0f) - divertY2;
@@ -124,40 +101,25 @@ void MotionVectors::Draw(const PerFrameContext& presetPerFrameContext, std::shar
124101

125102
if (posX > 0.0001f && posX < 0.9999f)
126103
{
127-
lineVertices[vertex].x = posX;
128-
lineVertices[vertex].y = posY;
129-
lineVertices[vertex].index = vertex;
130-
131-
lineVertices[vertex + 1] = lineVertices[vertex];
132-
lineVertices[vertex + 1].index++;
104+
lineVertices[vertex + 1] = lineVertices[vertex] = {posX, posY};
133105

134106
vertex += 2;
135107
}
136108
}
137109

138110
// Draw a row of lines.
139-
if (m_lastVertexCount >= vertex)
140-
{
141-
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(MotionVectorVertex) * vertex, lineVertices.data());
142-
}
143-
else
144-
{
145-
glBufferData(GL_ARRAY_BUFFER, sizeof(MotionVectorVertex) * vertex, lineVertices.data(), GL_STREAM_DRAW);
146-
m_lastVertexCount = vertex;
147-
}
148-
glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(vertex));
111+
m_motionVectorMesh.Update();
112+
m_motionVectorMesh.Draw();
149113
}
150114
}
151115

152-
glBindBuffer(GL_ARRAY_BUFFER, 0);
153-
glBindVertexArray(0);
116+
Renderer::Mesh::Unbind();
117+
Renderer::Shader::Unbind();
154118

155119
#ifndef USE_GLES
156120
glDisable(GL_LINE_SMOOTH);
157121
#endif
158122

159-
Renderer::Shader::Unbind();
160-
161123
glDisable(GL_BLEND);
162124
}
163125

src/libprojectM/MilkdropPreset/MotionVectors.hpp

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include "PerFrameContext.hpp"
44
#include "PresetState.hpp"
55

6-
#include <Renderer/RenderItem.hpp>
6+
#include <Renderer/Mesh.hpp>
77

88
#include <memory>
99

@@ -13,21 +13,18 @@ namespace MilkdropPreset {
1313
/**
1414
* @brief Draws a flexible motion vector field.
1515
*
16-
* This is broken right now, as it only renders a relatively static 1px point grid, with no apparent motion trails.
17-
* Milkdrop renders this as lines with trails.
18-
*
19-
* @todo Reverse-engineer the original Milkdrop code and reimplement it properly.
20-
* https://github.com/projectM-visualizer/milkdrop2/blob/f05b0d811a87a17c4624170c26c93bac39b05bde/src/vis_milk2/milkdropfs.cpp#L1239
16+
* Uses the same drawing logic as Milkdrop, but instead of reverse-propagating the motion data
17+
* on the CPU, projectM does this within the Motion Vector vertex shader. The Warp effect draws the
18+
* final U/V coordinates to a float texture, which is then used in the next frame to calculate the
19+
* vector length at the location of the line origin.
2120
*/
22-
class MotionVectors : public Renderer::RenderItem
21+
class MotionVectors
2322
{
2423
public:
2524
MotionVectors() = delete;
2625

2726
explicit MotionVectors(PresetState& presetState);
2827

29-
void InitVertexAttrib();
30-
3128
/**
3229
* Renders the motion vectors.
3330
* @param presetPerFrameContext The per-frame context variables.
@@ -36,20 +33,14 @@ class MotionVectors : public Renderer::RenderItem
3633
void Draw(const PerFrameContext& presetPerFrameContext, std::shared_ptr<Renderer::Texture> motionTexture);
3734

3835
private:
39-
struct MotionVectorVertex {
40-
float x{};
41-
float y{};
42-
int32_t index{};
43-
};
44-
4536
std::shared_ptr<Renderer::Shader> GetShader();
4637

4738
PresetState& m_presetState; //!< The global preset state.
4839

40+
Renderer::Mesh m_motionVectorMesh; //!< The Motion Vector geometry.
41+
4942
std::weak_ptr<Renderer::Shader> m_motionVectorShader; //!< The motion vector shader, calculates the trace positions in the GPU.
5043
std::shared_ptr<Renderer::Sampler> m_sampler{std::make_shared<Renderer::Sampler>(GL_CLAMP_TO_EDGE, GL_LINEAR)}; //!< The texture sampler.
51-
52-
int m_lastVertexCount{}; //!< Number of vertices drawn in the previous draw call.
5344
};
5445

5546
} // namespace MilkdropPreset

src/libprojectM/MilkdropPreset/Shaders/PresetMotionVectorsVertexShaderGlsl330.vert

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ precision mediump float;
22

33
layout(location = 0) in vec2 vertex_position;
44
layout(location = 1) in vec4 vertex_color;
5-
layout(location = 2) in int vertex_index;
65

76
uniform mat4 vertex_transformation;
87
uniform float length_multiplier;
@@ -17,7 +16,7 @@ void main() {
1716
// screen coordinates.
1817
vec2 pos = vertex_position;
1918

20-
if (vertex_index % 2 == 1)
19+
if (gl_VertexID % 2 == 1)
2120
{
2221
// Reverse propagation using the u/v texture written in the previous frame.
2322
// Milkdrop's original code did a simple bilinear interpolation, but here it was already

0 commit comments

Comments
 (0)