Controller deadzone, explained visually
Compare three common ways software can turn small stick values into a neutral output, using the same reproducible input.
On this page
A controller deadzone is a region near the stick’s center where an input is treated as zero. The phrase sounds like one setting, but the shape of that region and what happens after it can differ. This reference makes those choices visible with the same normalized X/Y input for each model.
The calculator uses an illustrative default of (0.15, 0.15) with threshold d = 0.20. Coordinates are dimensionless values from −1 to 1. They are examples, not a measurement of your controller. The comparison can help explain why two games or libraries respond differently even when their settings display the same number.
Compare one normalized input
Illustrative mathematical coordinates only. No controller is read.
Hard axial
Output (0.000000, 0.000000)
Input (0.150000, 0.150000) · d=0.200000
Hard radial
Output (0.150000, 0.150000)
Input (0.150000, 0.150000) · d=0.200000
Scaled radial
Output (0.010723, 0.010723)
Input (0.150000, 0.150000) · d=0.200000
Input magnitude r=0.212132. These are computed examples, not readings from your current device.
Same threshold, different result
At (0.15, 0.15), each component is below 0.20, so hard axial filtering returns (0, 0). The vector’s radial magnitude is about 0.2121, just outside a circular 0.20 region, so hard radial filtering retains (0.15, 0.15). Scaled radial filtering keeps its direction but starts its output just above zero. Identical thresholds do not define identical neutral regions: in these definitions, this diagonal input is neutral axially and nonzero radially.
Move X, Y, and d above to compare the outputs and diagrams. The diagrams show output positions; the outlined region is the model’s neutral shape. For axial filtering it is a square. For radial filtering it is a circle. The calculator does not use navigator.getGamepads(), send data anywhere, change controller settings, or test physical stick drift.
What happens beyond the boundary
Hard axial and hard radial models simply retain surviving input components; neither rescales them. Scaled radial instead maps the magnitude range from d…1 onto 0…1 while preserving direction. For input (0.30, 0.40), its magnitude is 0.50. At d = 0.20, the output magnitude is (0.50 − 0.20) / (1 − 0.20) = 0.375, giving approximately (0.225, 0.300). Scaling therefore begins at zero output at the threshold and reaches full magnitude at one.
All models treat values equal to d as inside the zero region in this reference. The scaled model caps magnitude at one, including for corner input (1, 1); the hard models retain its two components. Other software may use different boundaries, curves, clipping, or per-axis processing. The model names alone do not prove that two implementations behave identically.
Definitions and reproducibility
For each component a, hard axial returns zero when |a| ≤ d and otherwise returns a unchanged. Hard radial calculates r = hypot(x, y), returning zero when r ≤ d and otherwise retaining the vector. Scaled radial returns zero in that same inner region; outside it, it multiplies the unit direction by min(1, (r − d)/(1 − d)). Inputs must be finite, each coordinate must stay in [−1, 1], and d must be within [0, 0.95].
Version 1.0.0 uses double-precision arithmetic and the published JSON examples, with displayed values rounded to six decimal places. Download the formula, test cases, assumptions, and limitations. They contain the calculation conventions and complete examples for independent reproduction.
Published example cases
These server-rendered cases come from the version 1.0.0 public case file, so the reference remains understandable without the interactive script. Values below use six decimal places; JSON downloads retain full precision.
| Input (x, y), d | Hard axial | Hard radial | Scaled radial |
|---|---|---|---|
| (0.15, 0.15), 0.20 | (0, 0) | (0.15, 0.15) | (0.010723, 0.010723) |
| (0.30, 0.40), 0.20 | (0.30, 0.40) | (0.30, 0.40) | (0.225, 0.300) |
| (0.20, 0), 0.20 | (0, 0) | (0, 0) | (0, 0) |
| (1, 1), 0.20 | (1, 1) | (1, 1) | (0.707107, 0.707107) |
Sources and scope
These established techniques are explained in Microsoft DirectXTK’s GamePad documentation, Microsoft’s XInput documentation, Josh Sutphin’s original explanation, and Godot’s controller documentation. The algorithms are not invented here. The original contribution is this side-by-side comparison, selected examples, and reproducible numerical table.
The page reports no hardware measurements and recommends no universally best threshold. It does not assess firmware, wear, calibration, latency, or drift. For a live browser input view, use the Gamepad Tester. For a correction or clarification, contact us.