Currently, most aircrafts with a HUD have a parallax issue: when moving the viewpoint to the side, the HUD image just stays in place, whereas it should stay straight in front of the viewpoint. Because of this, as soon as one moves the viewpoint, indications such as flight path vector, pitch scale, radar returns positions, become wrong. For instance on the F-16: https://i.postimg.cc/9M66JgZL/f16-hud-deform.png
I am aware of two aircrafts which have solved this issue: the Saab 37 Viggen, and to some extent the Space Shuttle [1]. Both have the same solution: transformations are applied to the Canvas based on the view offset to compensate for parallax. Example with the Viggen: https://i.postimg.cc/2yNQHn6Q/viggen-hud-parallax.png The view was translated to the left, the HUD follows and the image remains straight in front of the view point (a part of the HUD image is cut because it is outside of the HUD mirror).
However this solution is not flawless: because the view movements are compensated by computing a transformation in Nasal and applying it to the canvas, the correction will always be at least 1 frame late. When using an IR head tracker (which allows to move the point of view a lot), this delay causes a very noticeable stuttering.
The solution I propose is to do all the required transformations in the HUD shader. I have implemented a modified version of the shader on the Viggen, available here:
https://github.com/NikolaiVChr/flightgear-saab-ja-37-viggen/tree/hud
Diff with the current FGData shader:
https://pastebin.com/r98siWen
It boils down to a couple of lines in the fragment shader:
- Code: Select all
vec2 relAngle = vec2(
atan(optical_relpos.y, -optical_relpos.x),
atan(optical_relpos.z, -optical_relpos.x)
);
TexCoord = (relAngle / vec2(radians(hud_width), radians(hud_height))) + 0.5;
Here, 'optical_relpos' is the vector from the viewpoint to the fragment position. The angle between this vector and the HUD forward axis determines the position sampled in the texture (TexCoord) after scaling/centering. Thus the HUD image is always displayed in front of the viewpoint, and has a constant angular size.
To get in more details:
- The optical axis (i.e. the direction to which the center of the hud image is mapped) is by default the '-x' axis in the HUD object model space.
In general, this corresponds to the aircraft forward axis. However, any rotate animation applied to the HUD object will be taken into account.
Additional rotations can be applied to the optical axis using effect parameters. - A common issue with canvas HUD beside parallax that the canvas is mapped to a slanted surface, which causes deformation. This is visible for instance on the F-16: https://i.postimg.cc/9M66JgZL/f16-hud-deform.png The red lines aligned with speed/altitude scales should appear parallel, but are not because the top of the HUD surface is closer to the viewpoint than the bottom.
This shader would also avoid this issue: in fact the Canvas image would be seen with no deformation no matter how weird the shape used as HUD object. - I believe the shader would make it easier to write the Canvas part of the HUD. Indeed, HUD elements position are typically given as pitch/yaw angles. With this shader, there is a linear relation between pitch/yaw angles and Canvas coordinates.
Of course porting existing aircrafts is another question...
- An old Viggen version without any parallax correction
- The current Viggen, with parallax correction in Canvas
- Parallax correction done in the shader
[1] The Shuttle correctly compensates lateral and vertical movements with translations, but not longitudinal movements, which should be compensated by scaling the canvas.