From d93e093fc7bc5f5f28eaa77514a094e322078d7d Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 2 Apr 2026 17:04:25 +0300 Subject: [PATCH] [thanos] Reparented surface to top widget and tuned particle physics. --- .../history/history_inner_widget.cpp | 22 +++++++++---------- .../SourceFiles/ui/effects/thanos_effect.cpp | 7 +----- .../ui/effects/thanos_effect_renderer.cpp | 14 +++++------- Telegram/shaders/thanos.vert | 2 +- Telegram/shaders/thanos_init.comp | 4 ++-- Telegram/shaders/thanos_update.comp | 4 ++-- 6 files changed, 22 insertions(+), 31 deletions(-) diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 84260f5f89..8d248beb53 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -4211,24 +4211,22 @@ void HistoryInner::captureViewForThanosEffect( view->draw(p, context); } - LOG(("ThanosEffect: captured view %1x%2, screenTop=%3, " - "image null=%4, allTransparent=%5") - .arg(viewWidth) - .arg(viewHeight) - .arg(screenTop) - .arg(image.isNull()) - .arg(image.pixelColor(viewWidth / 2, viewHeight / 2).alpha() == 0)); + const auto topLevel = window(); + if (!topLevel) { + return; + } if (!_thanosEffect) { - _thanosEffect = std::make_unique( - _scroll.get()); + _thanosEffect = std::make_unique(topLevel); } - const auto scrollRect = QRect(0, 0, viewWidth, visibleHeight); - _thanosEffect->setGeometry(scrollRect); + _thanosEffect->setGeometry(QRect(QPoint(), topLevel->size())); _thanosEffect->raise(); + + const auto localPos = QPoint(0, screenTop + _visibleAreaTop); + const auto globalPos = mapTo(topLevel, localPos); _thanosEffect->addItem( std::move(image), - QRect(0, screenTop, viewWidth, viewHeight)); + QRect(globalPos, QSize(viewWidth, viewHeight))); } HistoryInner::~HistoryInner() { diff --git a/Telegram/SourceFiles/ui/effects/thanos_effect.cpp b/Telegram/SourceFiles/ui/effects/thanos_effect.cpp index 0b795f493e..6f4041c061 100644 --- a/Telegram/SourceFiles/ui/effects/thanos_effect.cpp +++ b/Telegram/SourceFiles/ui/effects/thanos_effect.cpp @@ -71,15 +71,10 @@ void ThanosEffect::ensureSurface() { void ThanosEffect::showSurface() { if (const auto w = _surface ? _surface->rpWidget() : nullptr) { - const auto r = _parent->rect(); - LOG(("ThanosEffect: showSurface, parent rect=%1,%2 %3x%4") - .arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height())); - w->setGeometry(r); + w->setGeometry(_parent->rect()); w->show(); w->raise(); startUpdateTimer(); - } else { - LOG(("ThanosEffect: showSurface FAILED, no widget")); } } diff --git a/Telegram/SourceFiles/ui/effects/thanos_effect_renderer.cpp b/Telegram/SourceFiles/ui/effects/thanos_effect_renderer.cpp index 301507153f..420071b83d 100644 --- a/Telegram/SourceFiles/ui/effects/thanos_effect_renderer.cpp +++ b/Telegram/SourceFiles/ui/effects/thanos_effect_renderer.cpp @@ -24,7 +24,9 @@ constexpr auto kParticleStride = int(24); constexpr auto kQuadVertexCount = int(6); constexpr auto kQuadVertexStride = int(2 * sizeof(float)); constexpr auto kComputeWorkgroupSize = int(64); -constexpr auto kMaxPhaseDuration = 4.0f; +constexpr auto kMaxPhaseDuration = 6.0f; +constexpr auto kPhaseSpeed = 1.0f; +constexpr auto kTimeStepMultiplier = 1.0f; constexpr auto kMaxParticleCount = uint32_t(120000); const float kQuadVertices[kQuadVertexCount * 2] = { @@ -257,10 +259,6 @@ void ThanosEffectRenderer::render( return; } - LOG(("ThanosEffect render: %1 items, phase=%2") - .arg(_items.size()) - .arg(_items.front().phase)); - const auto pixelSize = rt->pixelSize(); const auto factor = style::DevicePixelRatio(); const auto viewW = float(pixelSize.width()) / factor; @@ -268,7 +266,7 @@ void ThanosEffectRenderer::render( bool needsInit = false; for (auto &item : _items) { - item.phase += dt * 2.0f; + item.phase += dt * kPhaseSpeed; if (!item.particlesInitialized) { needsInit = true; } @@ -297,7 +295,7 @@ void ThanosEffectRenderer::render( updateUni.particleCountX = item.particleCountX; updateUni.particleCountY = item.particleCountY; updateUni.phase = item.phase; - updateUni.timeStep = dt * 2.0f; + updateUni.timeStep = dt * kTimeStepMultiplier; rub->updateDynamicBuffer( item.computeUpdateUniformBuffer, 0, @@ -309,7 +307,7 @@ void ThanosEffectRenderer::render( if (needsInit) { for (auto &item : _items) { - if (item.phase <= dt * 2.1f) { + if (item.phase <= dt * kPhaseSpeed * 1.1f) { cb->setComputePipeline(_computeInitPipeline); cb->setShaderResources(item.computeInitSrb); const auto count = diff --git a/Telegram/shaders/thanos.vert b/Telegram/shaders/thanos.vert index dc37217025..a5f468cb2a 100644 --- a/Telegram/shaders/thanos.vert +++ b/Telegram/shaders/thanos.vert @@ -35,5 +35,5 @@ void main() { gl_Position = vec4(ndc, 0.0, 1.0); - v_alpha = clamp(inLifetime / 0.3, 0.0, 1.0); + v_alpha = clamp(inLifetime / 0.6, 0.0, 1.0); } diff --git a/Telegram/shaders/thanos_init.comp b/Telegram/shaders/thanos_init.comp index 1cfd8f4d2f..e412ad9b0c 100644 --- a/Telegram/shaders/thanos_init.comp +++ b/Telegram/shaders/thanos_init.comp @@ -43,12 +43,12 @@ void main() { uint s = gid * 3u + seed; float direction = hashFloat(s) * (3.14159265 * 2.0); - float speed = (0.1 + hashFloat(s + 1u) * 0.1) * 420.0; + float speed = (0.1 + hashFloat(s + 1u) * 0.1) * 320.0; Particle p; p.offset = vec2(0.0, 0.0); p.velocity = vec2(cos(direction) * speed, sin(direction) * speed); - p.lifetime = 0.7 + hashFloat(s + 2u) * 0.8; + p.lifetime = 1.5 + hashFloat(s + 2u) * 1.5; p._pad = 0.0; particles[gid] = p; diff --git a/Telegram/shaders/thanos_update.comp b/Telegram/shaders/thanos_update.comp index dc1c8d6220..4a73752490 100644 --- a/Telegram/shaders/thanos_update.comp +++ b/Telegram/shaders/thanos_update.comp @@ -46,8 +46,8 @@ void main() { Particle p = particles[gid]; p.offset += p.velocity * timeStep * particleFraction; - p.velocity.y += 120.0 * timeStep * particleFraction; - p.lifetime = max(0.0, p.lifetime - timeStep * particleFraction); + p.velocity.y += 80.0 * timeStep * particleFraction; + p.lifetime = max(0.0, p.lifetime - 0.6 * timeStep * particleFraction); particles[gid] = p; }