Articles

Houdini Global Variables: Using $F, $T and $RFSTART in Your Scenes

Includes one exclusive complete course

The exclusive course — a full production tutorial you won't find anywhere else, never sold alone.

Best Seller
Most Loved
Tutorial Camera Rig

ADVANCED CUSTOM CAMERA RIG

ANIMATION · CONSTRAINTS · CUSTOM UI

BUILD A FULLY CUSTOM CONSTRAINT-BASED CAMERA RIG IN HOUDINI WITH A CUSTOM UI PANEL. DESIGN FLEXIBLE SYSTEMS FOR PRECISE, CINEMATIC CAMERA ANIMATION ON ANY PROJECT.

€29.99

Freebies
Free Studio HDRI Pack box by Artivoxa showing 60 studio lighting setups with softboxes wrapped around the packaging

Studio HDRI Collection

ASSETS · EXR & HDR · 60 HDRIS

DOWNLOAD 60 STUDIO HDRIS CAPTURED IN A REAL PHOTO STUDIO. LIGHT YOUR PRODUCT AND BEAUTY RENDERS LIKE A PHOTOGRAPHER — SOFTBOX, LANTERN, STRIP AND GRID SETUPS, READY FOR ANY RENDERER.

FREE

ARTILABZ™

Everything You Need to master Houdini.

ARTILABZ™ gives you unlimited access to all Houdini courses, 3D assets, simulation files, textures and tools. updated every month.

01

Premium Houdini Tutorials

Full access to every course — fluid simulation, procedural FX, brand visuals and more.

02

Monthly New Content

Fresh tutorials and assets added every month — your library grows with you.

03

Instant Access to Everything

The moment you join, the full library is yours — no drip-feed, no waiting.

04

Project Files Included

Every tutorial comes with the full Houdini scene file — open every node, learn every detail.

FROM 14.99€/MONTH

Houdini Global Variables: Using $F, $T and $RFSTART in Your Scenes

Are you spending hours troubleshooting why your animation timing jumps? Do you struggle to keep your sequences consistent across frames? Many artists hit a wall when their expressions behave unpredictably.

In Houdini, timing and frame-based controls rely on global variables. Yet, variables like $F or $T can feel opaque. Without clear guidance, you might misapply them or overlook $RFSTART for offset control.

This guide focuses on demystifying $F, $T and $RFSTART. You’ll learn what each variable represents and how to implement them in your scenes. No more guessing frame numbers or manual offsets.

We’ll explore practical examples and best practices. Whether you need precise frame references or smooth time-based animations, this article will equip you with tools to streamline your workflow and avoid common pitfalls.

What are $F, $T and $RFSTART in Houdini and which scene tasks are they best for?

In Houdini, Houdini Global Variables like $F, $T and $RFSTART are built-in expressions evaluated at cook time. They parameterize your scene by pulling dynamic context—current frame, elapsed time or starting frame—into node parameters. Using these variables enhances procedural control and eliminates manual keying across DOP, SOP and shader networks.

The $F variable returns the integer current frame number. It excels for tasks requiring frame-accurate operations: driving transformations in geometry nodes, offsetting instance positions in copy SOPs, or triggering procedural events like particle bursts on specific frames. By leveraging $F, you maintain discrete synchronization with the timeline without manual keyframes.

$T provides the scene time in seconds as a floating-point value. When you need smooth, time-based variation—such as evolving noise patterns, real-time motion blur setups or velocity fields in fluid sims—$T ensures uniform results regardless of variable frame rates. For instance, rotating a turbine at 0.5 radians per second uses an expression like $T*0.5 for consistent speed.

The $RFSTART variable returns the first frame number in your render frame range. This is invaluable when you set up shot sequences or use batch renders: you can offset DOP simulations or cache file names relative to the sequence start. For example, naming flipbook outputs as “scene_” + ($F – $RFSTART) + “.png” resets counts at each shot automatically.

  • $F: frame-accurate triggers, instance offsets, discrete procedural events
  • $T: continuous time-driven motion, evolving noise, real-time shading effects
  • $RFSTART: shot-based offsets, cache naming, synchronized batch simulation starts

How do $F (frame) and $T (time) differ and how do you convert between them reliably?

Conversion formulas and realtime examples (fps, offset, negative frames)

The difference: $F returns the current integer frame number, while $T provides scene time in seconds. Reliable conversion requires knowing the frame rate (FPS) and the reference start frame ($RFSTART). Omitting the start offset leads to drift when frames start at values other than 1 or go negative.

Use these core formulas for precise mapping:

Conversion Formula
Frame → Time (F – RFSTART) / FPS
Time → Frame RFSTART + T * FPS

Example: FPS = 24, RFSTART = 10. At F = 36 → T = (36 – 10) / 24 ≈ 1.083s. At T = 2.5s → F = 10 + 2.5 * 24 = 70.

Handling subframe sampling and non-integer frame values in expressions

Houdini supports subframe evaluation, so time isn’t restricted to whole frames. While $F always returns an integer, you can access fractional frames via $T or the float frame variable ($FF or @Time*FPS in VEX). Enable “Allow Fractional Frames” on key parameters or activate Subframe Sampling in DOP imports to interpolate motion correctly.

In VEX wrangles and channel references, sample channels at non-integer indices using functions like chf() or sample(). For example, to fetch a motion channel at frame 12.37: chf("path/to/channel", 12.37). Combining lerp() or fit() ensures smooth value interpolation across subframes for realistic, jitter-free animation.

How to use $RFSTART to control prerolls, cached simulations and retimed playback

$RFSTART returns the first frame of your retimed sequence, factoring in any Retime SOP or TimeBlend. Unlike $F (current frame) or $SF (simulation start), $RFSTART shifts Houdini’s internal timebase to match your post‐retime timeline. This ensures that downstream solvers, caches and expressions align with the frame at which you intend playback to begin.

To implement a preroll for a Flip or Rigid Body sim, set your solver’s “Start Frame” parameter to an expression like $RFSTART - preroll_amount. For example, with a 24-frame preroll use $RFSTART - 24. The solver then runs from $RFSTART - 24 up to $RFSTART, settling particles or rigid bodies before your visible playback. This method avoids hard‐coding negative start frames and automatically adapts if you change retime speed or offset.

When writing cached simulations with ROP Geometry, include $RFSTART in your file paths to distinguish preroll and main cache passes. For instance:
sim_preroll.$F.bgeo and
sim_main.$RFSTART.bgeo. During playback, the DOP Import or File SOP can reference sim_main.$RFSTART.bgeo so that it reads only the frames aligned to your retimed timeline, preventing unwanted preroll frames from loading in the viewport.

In VEX Wrangles or CHOP channels, use $RFSTART to normalize frame attributes for retimed playback. Example:
float speed = ch("speed");
@Time = (@Frame - $RFSTART)/speed + $RFSTART;

This computes a new time attribute that scales your animation by speed while preserving the offset of your retime. As a result, your procedural rigs, constraints and time‐dependent noise patterns remain in sync after any retiming adjustment.

How to write robust parameter expressions and VEX that use $F, $T and $RFSTART

In procedural workflows it’s common to rely on $F and $T for driving animation or sim timing. However, hard-coded expressions break when playback ranges or reference frames shift. To avoid this, encapsulate frame info in HDA parameters or detail attributes and reference those consistently. This approach insulates your setup from timeline changes and ensures your expressions stay accurate across context loads and version updates.

Inside an HDA you can expose a “Simulation Start Frame” parameter that reads $RFSTART from a dedicated null or reference node. Use an HScript default expression like detail(“../REF_NODE”, “rfstart”, 0) to initialize that parameter. Downstream you replace direct $RFSTART tokens with ch(“sim_start”) so path changes won’t break your network and users can override the start frame at will.

To remap any frame-dependent value to a normalized 0–1 range, combine frame variables with fit() or lerp(). For example, in a parameter field:
fit(($F – ch(“sim_start”)), 0, ch(“duration”), 0, 1).
This expression subtracts the start frame, then scales the result by the total duration parameter. Embedding your own controls means you avoid hidden dependencies and maintain clarity when debugging or sharing HDAs.

When writing VEX, prefer @Frame and @Time over $-variables. You can pull a start frame detail attribute with getdetailattrib(0, “sim_start”, 0). Then compute a normalized time:
float sim_start = getdetailattrib(0, “sim_start”, 0);
float tnorm = (@Frame – sim_start) / ch(“duration”);
Use tnorm in further procedural operations. This method stays consistent even in Background Sim ROPs or when you override FPS in simulation settings.

Beware these common pitfalls:

  • Mixing $T with $F leads to mismatches if FPS changes.
  • Direct $RFSTART references break when nodes are copied or moved.
  • HScript variables don’t update inside locked HDAs without ch() overrides.

By centralizing your time and frame logic into controlled parameters and accessing them through channel() expressions or VEX detail calls, your rigs remain adaptable. Always document your start, end, and duration parameters, and prefer normalized ranges over raw frames. This ensures your setups scale across shots, FPS targets, and complex pipeline requirements without hidden frame-dependency issues.

What common mistakes happen with these globals and how to debug timing issues in complex scenes?

When working with $F, $T, and $RFSTART in intricate Houdini setups, artists often confuse frame-based and time-based variables. For example, using $T (seconds) in an expression designed for integer frames can produce unexpected float values. Similarly, forgetting to adjust $RFSTART when a scene’s start frame shifts leads to animation offsets that only become apparent during simulation playback.

Another frequent oversight concerns DOP or particle simulations: $F inside a DOP network refers to the current substep frame, not the global frame. Mixing it with SOP-level $F can trigger drift or jitter in procedural animation. Additionally, hardcoding start-frame offsets instead of relying on $RFSTART makes publishing to different shot ranges error-prone.

Debugging these timing issues requires isolating the variable in question and visualizing its output. Houdini’s Geometry Spreadsheet can display per-point attributes evaluated with your expression. For scene-wide checks, use CHOPs to plot channel data over time, or add a temporary Add SOP with a curve that maps $T or $F variations to spatial positions or colors.

  • Inspect attribute values per frame in the Geometry Spreadsheet to confirm correct increments.
  • Use a TimeShift or TimeBlend node to freeze or retime clips and verify dependency on $RFSTART.
  • Create a CHOP network: import your variable as a channel, view in the Channel Monitor for substep insights.
  • Leverage the Performance Monitor (Windows > Performance Monitor) to spot expensive recooks triggered by changing globals.
  • Temporarily drive viewport color with your variable (via a Color SOP) to see real-time fluctuations across frames.