From e0475aa880fc12ae3feec0e5e96815a721e0c911 Mon Sep 17 00:00:00 2001 From: Matias Date: Wed, 16 Jul 2025 22:57:26 +0200 Subject: [PATCH] perf: avoid useless copy of particle positions in renderpass --- include/wobblywindow.h | 6 ++++- src/main.cpp | 5 +--- src/renderpasses.cpp | 15 +++++------- src/wobblywindow.cpp | 53 +++++++++++++++++++++++++++--------------- 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/include/wobblywindow.h b/include/wobblywindow.h index 5734056..702d3f6 100644 --- a/include/wobblywindow.h +++ b/include/wobblywindow.h @@ -17,7 +17,9 @@ class CWobblyWindow { static inline float s_dampingStrength = 12.f; static inline float s_drag = 0.4f; - std::vector m_particles; + std::vector m_particlePositions; + std::vector m_particleVelocities; + std::vector m_targetPositions; std::optional m_grabPosition {std::nullopt}; Vector2D m_windowMovement; @@ -25,5 +27,7 @@ class CWobblyWindow { CWobblyWindow(); bool step(Time::steady_tp time); + + void applyMovement(const Vector2D& movement); }; #endif diff --git a/src/main.cpp b/src/main.cpp index 4a5cd16..8f87929 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -73,10 +73,7 @@ void hkRenderWindow( wobble.m_grabPosition = std::nullopt; } - wobble.m_windowMovement = (pos - g_windowPositions[pWindow]) / windowSize; - for (auto&& particle : wobble.m_particles) { - particle.position -= wobble.m_windowMovement; - } + wobble.applyMovement((pos - g_windowPositions[pWindow]) / windowSize); // update last pos g_windowPositions[pWindow] = pos; diff --git a/src/renderpasses.cpp b/src/renderpasses.cpp index 8c87e82..03e8d66 100644 --- a/src/renderpasses.cpp +++ b/src/renderpasses.cpp @@ -165,16 +165,13 @@ void CRenderWobblyWindowPassElement::draw(const CRegion& damage) { // TODO: these should never be nan // if (not std::isnan(wobble.m_particles[0].position.x)) { - // TODO: we need the particle positions in their own vec, to avoid this copy - std::vector verts; - verts.reserve(vertsPerRow * vertsPerRow * 2); - for (auto&& particle : wobble.m_particles) { - verts.push_back(particle.position.x); - verts.push_back(particle.position.y); - } - GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO)); - GLCALL(glBufferSubData(GL_ARRAY_BUFFER, 0, verts.size() * sizeof(float), verts.data())); + GLCALL(glBufferSubData( + GL_ARRAY_BUFFER, + 0, + wobble.m_particlePositions.size() * sizeof(float), + wobble.m_particlePositions.data() + )); // } } else { // restore default verts diff --git a/src/wobblywindow.cpp b/src/wobblywindow.cpp index 4359c4f..cd6fe1f 100644 --- a/src/wobblywindow.cpp +++ b/src/wobblywindow.cpp @@ -5,11 +5,15 @@ CWobblyWindow::CWobblyWindow() { auto&& verts = CRenderWobblyWindowPassElement::s_baseVerts; - m_particles.reserve(verts.size() / 2); - m_targetPositions.reserve(verts.size() / 2); + // copy directly + m_particlePositions = verts; + + // init empty + m_particleVelocities.resize(verts.size() / 2); + + m_targetPositions.reserve(verts.size() / 2); for (unsigned int i {}; i < verts.size(); i += 2) { - m_particles.push_back(SParticle {Vector2D {verts[i], verts[i + 1]}, {}}); m_targetPositions.push_back(Vector2D {verts[i], verts[i + 1]}); } } @@ -22,42 +26,44 @@ bool CWobblyWindow::step(Time::steady_tp time) { Vector2D totalVel {}; - for (unsigned int i {}; i < m_particles.size(); i++) { - auto&& particle = m_particles[i]; - auto&& particlePositon = particle.position; + for (unsigned int i {}; i < m_particlePositions.size() / 2; i++) { + // TODO: avoid float -> double promotion + const auto& pos = Vector2D {m_particlePositions[i * 2], m_particlePositions[i * 2 + 1]}; + auto&& vel = m_particleVelocities[i]; auto&& targetPosition = m_targetPositions[i]; - const Vector2D directionToTarget = targetPosition - particlePositon; + const Vector2D directionToTarget = targetPosition - pos; if (m_grabPosition.has_value()) { - const float distanceToDragPosition = m_grabPosition.value().distance(particlePositon); + const float distanceToDragPosition = m_grabPosition.value().distance(pos); const float dragStrength = std::clamp(distanceToDragPosition, 0.f, 1.f); - particle.position += m_windowMovement * dragStrength; + m_particlePositions[i * 2] += m_windowMovement.x * dragStrength; + m_particlePositions[i * 2 + 1] += m_windowMovement.y * dragStrength; } - const Vector2D springForce = - directionToTarget * s_springStrength - particle.velocity * s_dampingStrength; - particle.velocity += springForce * dt; + const Vector2D springForce = directionToTarget * s_springStrength - vel * s_dampingStrength; + vel += springForce * dt; // Apply drag - const Vector2D dragForceVector = (particle.velocity * particle.velocity) * -s_drag; + const Vector2D dragForceVector = (vel * vel) * -s_drag; // * Area - auto dir = particle.velocity; + auto dir = vel; float magnitude = dir.normalize(); if (magnitude != 0) - particle.velocity += (dragForceVector * dir) * dt; + vel += (dragForceVector * dir) * dt; // Apply velocity - particle.position += particle.velocity * dt; + m_particlePositions[i * 2] += vel.x * dt; + m_particlePositions[i * 2 + 1] += vel.y * dt; - totalVel += particle.velocity; + totalVel += vel; } - const bool shouldEnd = - m_windowMovement.size() == 0 and totalVel.size() / m_particles.size() < .001f; + const bool shouldEnd = m_windowMovement.size() == 0 + and totalVel.size() / (m_particlePositions.size() / 2.f) < .001f; // std::println( // "Top left: {}, totalVel: {}", @@ -68,3 +74,12 @@ bool CWobblyWindow::step(Time::steady_tp time) { return shouldEnd; } + +void CWobblyWindow::applyMovement(const Vector2D& movement) { + m_windowMovement = movement; + + for (unsigned int i = 0; i < m_particlePositions.size() / 2; i++) { + m_particlePositions[i * 2] -= movement.x; + m_particlePositions[i * 2 + 1] -= movement.y; + } +}