Nebula Flythrough

Turn one still astro image into a cinematic MP4 flythrough — no video software required.

Video software for people who don't want to learn video software. This tool takes your starless and stars images, animates a zoom-and-pan "camera" through them, composites them with blend modes, applies motion effects like warp-speed streaks, chromatic aberration, and depth parallax, and exports a finished MP4. No DaVinci Resolve, no Filmora, no After Effects, no keyframe timelines — three panels of controls and a Preview window. GPU-accelerated when a GPU is available, falls back to CPU otherwise.

1. What the tool does

You give it between one and three images (starless is required, mid layer is optional, stars layer is optional). For each layer you configure a "camera move" — where the camera starts, where it ends, how fast it zooms, how it eases between the two. On export, the tool renders every frame at your target resolution and FPS, composites the layers together, and writes an MP4.

Because each layer can have its own zoom speed, you get parallax for free: zoom the starless layer from 1× to 6× and the stars layer from 1× to 4×, and the stars appear to drift behind the nebula as you fly through it. Add the "Nebula depth warp" effect and bright structures actually come forward on the Z axis.

2. The three-layer system

LayerWhat it isWhere it sits
Starless (required)Your nebula image with stars removed. Usually from GraXpert, StarXTerminator, or the SASpro Remove Stars tool.Bottom. The base of the composite.
Mid (optional)Any extra image you want blended in — a narrowband channel, a different stretch of the same data, a second nebula, text overlay, anything.Middle. Composited over the starless layer using the Blend mode and Opacity you pick.
Stars (optional)The stars-only output from your star removal step.Top. Composited over the mid+starless result, usually using Screen so stars glow through.

Each layer has independent zoom, center, easing, lens effects, blend mode, and opacity. The compositing order is fixed:

base = blend( starless, mid, mid_blend, mid_opacity ) final = blend( base, stars, stars_blend, stars_opacity )

3. Common workflow

  1. Prepare your images in SASpro. Open your fully-processed nebula shot, then run a star-removal step (Remove Stars tool) to produce a starless view and a stars-only view. Both now exist as docs in SASpro.
  2. Open Nebula Flythrough from the Tools menu.
  3. Pick sources for each layer from the three Source dropdowns. Starless is required; Mid is "-- none --" by default; Stars is "-- select --".
  4. Set the camera for the starless layer: Zoom start 1.0, Zoom end 6.0 is a reliable "fly in" setting. Click a point on the picker image to set the Start center, then click somewhere else for the End center (or just leave both at 0.5).
  5. Set the camera for the stars layer: usually a slower zoom (e.g. 1.0 to 3.0) and the same center points. The zoom difference creates parallax.
  6. Set the output size, FPS, and duration in the Output panel. 1920×1080 at 30 fps for 10 s is a solid default (300 frames).
  7. Scrub the preview slider to inspect intermediate frames. Hit Play Preview to see the whole motion at low res.
  8. Enable effects as desired: Nebula depth warp for 3D feel, Zoom blur for warp speed, Chromatic aberration for sci-fi vibe.
  9. Click Export Video... and pick an MP4 destination. The tool renders at full source resolution (not the working preview resolution) and shows per-frame progress.

4. Camera controls per layer

Each layer panel has the same core controls.
Zoom x: Start / End — zoom factor at t=0 and t=1. 1.0 means "fit the frame to source"; higher values zoom in. Range 1.0 to 50.0.
center start / end — fractional image coordinates (0.0 to 1.0) for the zoom center at t=0 and t=1. Panning is implicit: if start center = end center, the camera stays locked and only zooms. If they differ, the camera pans.
Easing — Linear, Ease In (slow start, fast end), Ease Out (fast start, slow end), Ease In-Out (slow both ends, fast middle — most cinematic).
Pick Start / End center — click one of these buttons, then click a point on the big preview image on the left to set that center. Right-click the picker to cancel. Only one layer at a time can be in "pick mode"; selecting another layer's pick button cancels the current one.
Blend mode (mid and stars) — how this layer combines with the layers beneath. Screen is the default for stars; Soft Light / Overlay are nice for mid.
Opacity (mid and stars) — 0.0 to 1.0 blend of this layer into the composite.

5. Lens effects

Each layer has an identical "Lens Effects" box with four optional effects, plus a master "Ramp effects with zoom" checkbox that controls when they kick in.

EffectWhat it doesGood for
Nebula depth warpTreats image luminance as a 3D height field and shifts bright pixels toward you as you zoom. Includes separate Depth blur (smooth the heightmap) and Invert depth (dark = closer) controls.Any nebula where the bright structures should feel "in front of" the dim backdrop. Dusty structures become visibly volumetric.
Radial edge stretchPincushion / barrel distortion. Positive values stretch the edges outward; negative values compress them inward.Fisheye-ish immersion, exaggerating the "flying through a tunnel" sensation.
Zoom blurMulti-sample streaking along the radial direction from the zoom center.Warp-speed stars. Pair with high zoom and Ease In for a dramatic acceleration.
Chromatic aberrationShifts the red channel inward and blue channel outward, each by a few percent per unit strength.Sci-fi aesthetic, lens-realism look, "cheap telescope" feel. Subtle values (0.1-0.3) sell it; higher is comic-book.
Ramp effects with zoom. With this checkbox on (default), the effects scale with the velocity of the camera's zoom, not the elapsed time. So an effect at full strength only hits when the camera is at its fastest point — meaning Ease In-Out gives you a lovely accelerate-then-decelerate warp arc, while Linear keeps the effect pinned at the strength you dialed in. Turn this off if you want the effect at constant strength throughout.

6. Blend modes

Twelve blend modes are available for the mid and stars layers:

ModeWhen to use
ScreenDefault for the stars layer. Preserves star brightness, invisible on black backgrounds. Also good for additive glow effects on mid.
AddHarder than Screen — can blow out highlights. Use for intentionally burning in a layer.
AverageSimple arithmetic mean. A gentle 50/50 blend.
Max / LightenKeep the brighter pixel per channel. Alternative to Screen for stars.
MultiplyDarken-only. Good for burning in dust lanes or shadow layers.
OverlayContrast boost — multiplies darks, screens lights. Classic "pop" blend for mid.
Soft LightGentle contrast boost. Pleasant for subtle enhancements.
Hard LightAggressive contrast boost — like Overlay but condition is on the top layer.
DifferenceShows where layers disagree. Useful for debugging alignment, less for aesthetics.
Color DodgeBrightens based on top layer. Very intense; use sparingly.
DarkenKeep the darker pixel per channel.
Threshold MaskPixels brighter than Threshold sit on top of the base; dimmer pixels are transparent. Great for using stars as a cutout. Threshold and Feather sliders appear when this mode is selected.

7. Workflow recipes

Classic nebula flythrough with parallax. Starless zoom 1 → 6, Stars zoom 1 → 3.5, both centered on the same bright region. Easing: Ease In-Out. Stars blend: Screen. Duration 12 s at 30 fps. The 1.7× zoom gap between layers creates genuine parallax — stars appear to drift behind the nebula as you dive in.
Warp-speed hyperdrive. Starless zoom 1 → 30 (yes, really), Stars zoom 1 → 20, both centered on the same point. Easing: Ease In (slow start, violent acceleration). Enable Zoom blur on both at ~0.6 strength and Chromatic aberration at ~0.3. Enable "Ramp effects with zoom" so the streaks only appear once the camera starts moving fast. Duration 5-8 s. The Star Wars jump to hyperspace, built from your Orion image.
Volumetric nebula with depth warp. Starless layer only (or very low-opacity stars). Enable Nebula depth warp at strength 0.5, depth blur 10, inverted off (so bright = closer). Zoom 1 → 4 slow Ease In-Out. The bright structures of the nebula actually come forward relative to the background during the zoom — adds a strong 3D feel without needing a stereo pair.
Three-layer comparison video. Starless on bottom, your Ha-OIII-SII palette on the mid layer (blend: Overlay at 0.5 opacity), stars on top (Screen at 1.0). As you zoom in, you reveal both the palette and the stars at once. Great for before/after storytelling.
Stars-as-cutout effect. Mid layer = a nebulosity image (perhaps a different band or a more aggressive stretch); Stars blend set to Threshold Mask with threshold 0.15 and feather 0.08. Where the stars are bright, they punch through to the mid layer underneath; everywhere else the base nebula shows through. Produces a dreamy "stars twinkling through dust" look.
Slow drift reveal. Both layers at zoom 1.5 → 2.0 (barely any zoom), with Start center at one point and End center at a different point. Easing: Linear. Duration 20 s. This is a gentle pan across your image, revealing it slowly — perfect for YouTube video intros or background B-roll in observing videos. Add light depth warp (0.2) for subtle motion.
Opening or closing a video with zoom-out from constellation. Starless and Stars at zoom 10 → 1 (zoom out), centered on the brightest nebula region. Easing: Ease Out. Starts tight on a nebula, pulls back to reveal the full constellation / wide field over 8-10 s. Classic documentary intro-opening shot.

8. Preview vs. export resolution

The Working res dropdown (in the Output panel) controls the resolution used for the live preview — SD, HD, 2K, 4K, or Full. Smaller working resolutions make the preview more responsive and depth-map calculations faster, especially for very large source images.

Export always uses full source resolution. The working resolution only affects the on-screen preview. When you hit Export, the renderer reaches back to the original full-size images and crops from them, so a 32 megapixel source produces 32-megapixel-fidelity crops regardless of your working-res pick. This means a flythrough at 1920×1080 output stays sharp even at 10× zoom — the pixels are drawn from the original data, not from a downsampled copy.

9. GPU vs. CPU rendering

If PyTorch is installed and a CUDA GPU or Apple Silicon MPS device is available, rendering runs on the GPU automatically. The status line during export shows [GPU] or [CPU] per frame so you can confirm which backend is active. The pipeline silently falls back to CPU if GPU rendering fails on any frame — your render will finish either way, just slower on CPU for high resolutions.

Typical speedup from GPU: 5-15× on a modern discrete card, 3-5× on Apple Silicon. For a 10-second 1080p30 render (300 frames), that's the difference between coffee-break and an entire movie.

10. Technical details

The easing curves, the torus-wrapped zoom crop, the depth-aware parallax, the blend-mode math, the motion-coupled effect ramp, and the GPU grid-sample pipeline.

10.1 Easing functions

Four easing curves map normalized time t ∈ [0, 1] to an eased t ∈ [0, 1]:

\text{Linear: } f(t) = t
\text{Ease In: } f(t) = t^3
\text{Ease Out: } f(t) = 1 - (1 - t)^3
\text{Ease In-Out: } f(t) = 4t^3 \text{ for } t < 0.5, \quad f(t) = 1 - \frac{(2 - 2t)^3}{2} \text{ for } t \geq 0.5

Each layer picks its own curve independently — a common technique is Ease In for the starless layer and Linear for the stars layer, which makes the nebula accelerate forward while the starfield slides past at constant speed, selling parallax more strongly.

10.2 Zoom crop with torus wrap

Given a zoom factor z and center (cx, cy) in fractional image coordinates, the crop window dimensions are:

W_{\mathrm{crop}} = W / z, \quad H_{\mathrm{crop}} = H / z

The window spans:

x \in [c_x - W_{\mathrm{crop}}/2, \; c_x + W_{\mathrm{crop}}/2]

and samples are taken on a regular grid interpolated into an output of size (out_h, out_w). When the crop window extends beyond the image boundary — common at high zoom near the edge — the coordinates wrap modulo (W, H):

x_{\mathrm{src}} = x \; \mathrm{mod} \; W, \quad y_{\mathrm{src}} = y \; \mathrm{mod} \; H

This is a torus wrap boundary mode — the image is treated as a seamlessly tileable texture. Unlike reflect or clamp modes, it never produces visible edge streaks or mirror reflections at the frame boundary, which was a visual flaw of earlier approaches. OpenCV's cv2.remap with BORDER_WRAP handles this on the CPU path; on GPU, normalized coordinates are folded with a custom modulo on [-1, 1].

10.3 Depth-aware parallax zoom

With Nebula depth warp enabled, each output pixel's source location is perturbed radially based on local luminance. The pipeline:

  1. Build a depth map from the source: luminance Y = 0.299R + 0.587G + 0.114B, Gaussian-blurred by σ (default 8 px) to avoid noise, optionally inverted (dark = closer), then normalized to [0, 1].
  2. For each output pixel (u, v) in normalized grid coordinates u, v ∈ [-0.5, 0.5], compute the base source location (x₀, y₀) using the zoom crop math above.
  3. Compute the radial direction from the zoom center:
    (n_x, n_y) = \left(\frac{dx}{\sqrt{dx^2 + dy^2}}, \frac{dy}{\sqrt{dx^2 + dy^2}}\right)
    where (dx, dy) = (u · Wcrop, v · Hcrop).
  4. Sample the depth map at the base source location to get d, and center around 0.5:
    d_c = d - 0.5
  5. Compute the parallax shift in pixels, scaled by both the user strength sd and the current zoom:
    p = d_c \cdot s_d \cdot (z - 1) \cdot 2
    The (z - 1) factor means parallax activates only during zoom — at z = 1 (fit to frame), the effect contributes nothing. The factor of 2 is a visual calibration constant.
  6. Apply the shift radially:
    (x_s, y_s) = (x_0 - n_x p, \; y_0 - n_y p)
    Bright regions (d > 0.5) move toward the camera center as you zoom in, appearing closer; dark regions move outward, appearing further.
  7. Sample the source image at (xs, ys) with torus wrap.

The result is per-pixel differential zoom — the nebula's brightest arcs lean forward during the fly-in, dust lanes recede, all without a true 3D model.

10.4 Blend-mode math

All blend modes operate pixelwise, per channel, on float32 values in [0, 1]. a is the base (lower) layer, b is the layer being blended on top:

\mathrm{Screen}(a, b) = 1 - (1 - a)(1 - b)
\mathrm{Add}(a, b) = \mathrm{clip}(a + b, 0, 1)
\mathrm{Multiply}(a, b) = a \cdot b
\mathrm{Overlay} = 2ab \text{ if } a < 0.5, \text{ else } 1 - 2(1-a)(1-b)
\mathrm{SoftLight}(a, b) = (1 - 2b)\,a^2 + 2ab
\mathrm{Difference}(a, b) = |a - b|
\mathrm{ColorDodge}(a, b) = \min\left(\frac{a}{1 - b}, 1\right)

Hard Light swaps the condition in Overlay to test b < 0.5 instead of a. Max/Lighten take max(a, b); Darken takes min(a, b); Average is (a + b)/2. The Soft Light formula is the Pegtop variant — simpler and more stable than the Photoshop recipe, and visually indistinguishable for typical use.

After the blend, opacity α interpolates between base and blended:

\mathrm{out} = a + \alpha \cdot (\mathrm{blend}(a,b) - a)

10.5 Threshold Mask (special blend mode)

Threshold Mask is an alpha composite rather than a pixelwise blend. Luminance of the top layer m drives a per-pixel alpha:

Y_m = 0.2126\, R_m + 0.7152\, G_m + 0.0722\, B_m
\alpha = \mathrm{clip}\!\left(\frac{Y_m - \tau}{\sigma}, 0, 1\right)

where τ is the Threshold slider and σ is the Feather slider. The final result is a straight over-composite:

\mathrm{out} = a (1 - \alpha) + m \cdot \alpha

This gives you a clean mask that fades smoothly within a σ-wide luminance band around τ. For a stars layer, setting τ ≈ 0.15 and σ ≈ 0.08 makes the stars sit cleanly on top of the base while the dark gaps between stars reveal the layers beneath.

10.6 Radial edge stretch

For each pixel at offset (dx, dy) from the zoom center, with half-diagonal of the frame as the normalizing length, the normalized radius is:

r = \frac{\sqrt{dx^2 + dy^2}}{\mathrm{half\_diag}}

and the source sample location becomes:

(x_s, y_s) = (x - dx \cdot k \cdot r^2, \; y - dy \cdot k \cdot r^2)

where k is the strength slider. The r² factor means the center is unaffected while edges distort most — standard radial distortion. Positive k gives barrel distortion (edges pushed outward); negative k gives pincushion (edges pulled inward). Range of the strength slider is [-0.5, 0.5].

10.7 Zoom blur (warp-speed streaks)

Zoom blur is implemented as a multi-sample accumulation at progressive zoom levels. For N samples (default 12):

z_i = 1 + (z_{\max} - 1) \cdot \frac{i}{N - 1}
w_i = 1 - \frac{i}{N - 1} \cdot 0.6

where zmax = 1 + 0.25 · s. The samples are weighted so the undistorted (i=0) sample has weight 1 and the most-zoomed sample has weight 0.4, giving a trailing look rather than a smeared one. The weighted average is blended into the original image at blend factor 0.7 · s:

\mathrm{acc} = \frac{\sum_i w_i \cdot \mathrm{crop}_i}{\sum_i w_i}
\mathrm{out} = (1 - \beta) \cdot \mathrm{img} + \beta \cdot \mathrm{acc}, \quad \beta = 0.7 s

Visually: stars become radial streaks pointing away from the zoom center, with the streak length controlled by the strength slider.

10.8 Chromatic aberration

Red and blue channels are independently zoomed with a small offset relative to green:

\Delta_{\max} = 0.03 \cdot s
z_R = 1 - \Delta_{\max}, \quad z_B = 1 + \Delta_{\max}

Red zooms in (shifts inward toward center), blue zooms out (shifts outward toward edges). The green channel is left unchanged. This mimics the way real refractors with imperfect correction spread colors radially at the edges of the field, giving a lens-realism feel. At s = 1 (max slider), the shift is 3% — enough to see at the frame edges, invisible near center.

10.9 Motion-coupled effect ramp

With "Ramp effects with zoom" enabled, each effect's strength is modulated by the current zoom velocity, not by elapsed time. For eased time function f(t), the velocity at time t is approximated by a small central difference:

v(t) = \frac{f(t + \varepsilon) - f(t - \varepsilon)}{2\varepsilon}

normalized to a visual ramp:

\mathrm{ramp}(t) = \mathrm{clip}\!\left(\frac{v(t)}{3}, 0, 1\right)

with ε = 0.005. The effect strength the user set in the slider is then multiplied by ramp(t) before being applied. For an Ease In curve, v(0) ≈ 0 and v(1) is maximum — so chromatic aberration and zoom blur both ease in with the camera's acceleration. For Linear, v is constant and the effects stay pinned at their slider values. The divisor 3 is empirical: it means Ease In-Out and Linear end up at roughly the same peak effect strength despite having very different velocity curves.

10.10 Compositing order

The final frame is built in two steps:

\mathrm{base} = \mathrm{blend}(\mathrm{starless}, \mathrm{mid}, \mathrm{mode}, \alpha)
\mathrm{final} = \mathrm{blend}(\mathrm{base}, \mathrm{stars}, \mathrm{mode}, \alpha)

When the mid layer is absent, step 1 is skipped and base = starless. When the stars layer is absent, step 2 is skipped and the final frame is base. The default stars blend is Screen with opacity 1.0, which reproduces the classic "stars-plus-nebula" composite you'd otherwise do manually.

10.11 GPU acceleration via grid_sample

When PyTorch is available with a CUDA or MPS backend, the zoom crop, radial stretch, zoom blur, chromatic aberration, and depth warp are all implemented via torch.nn.functional.grid_sample operating on NCHW tensors. The GPU-side torus wrap is implemented by folding normalized grid coordinates into [-1, 1]:

def _wrap_norm_coords(coords): return ((coords + 1.0) % 2.0) - 1.0

which is equivalent to the modulo wrap in image space. The GPU path uses padding_mode="zeros" because the wrap already keeps all coordinates inside [-1, 1], so the zero-padding fallback is never actually triggered.

Depth maps are uploaded once per render to a (1, 1, H, W) tensor, then sampled on-GPU each frame. Images are stored on-GPU as (1, 3, H, W) float32. Each layer composite is a Python function call that returns a tensor, so blend modes can chain without any CPU round-trip — only the final (1, 3, out_h, out_w) frame is pulled back to numpy and converted to BGR uint8 for the OpenCV MP4 writer.

Credits. Nebula Flythrough — the three-layer compositor with mid-layer blend modes, the motion-coupled effect ramp, the torus-wrapped zoom crop, the luminance-driven depth-parallax warp, the warp-speed zoom blur, the Threshold Mask alpha-cutout mode, the preview-vs-export resolution system, and the unified CPU/GPU render pipeline — is original work by Franklin Marek for SetiAstro Suite Pro. Standard components credited to the community: OpenCV (cv2.remap with BORDER_WRAP, cv2.VideoWriter with mp4v FOURCC) for CPU warping and video output; PyTorch (grid_sample) for GPU warping with CUDA / MPS backends; the cubic easing curves (Ease In / Out / In-Out) are the standard animation-industry formulas; the Pegtop Soft Light formula is widely used as a more stable alternative to the Photoshop recipe; the Rec.709 luminance weights (0.2126, 0.7152, 0.0722) are the standard color-space constants; chromatic aberration via per-channel radial zoom is a classical lens-simulation approach.