-
-
Notifications
You must be signed in to change notification settings - Fork 6
File Size Optimization
As the first point of interaction between the actual HUD and the user, file size optimization/reduction was an important consideration in the development of Xhud. As such, various techniques for reducing file size while maintaining features and quality were developed/adopted in the making of Xhud.
Probably the largest source of file size bloat in custom HUDs are custom materials, which are essentially image files called upon and manipulated by the game. These include: panels, backgrounds, buttons, icons, killfeed icons, etc. and can quickly add up. For example, the size of the materials folders in some common HUDs are:
- HypnotizeHud: 26MB / 30MB total
- BudHud: 29MB / 40MB total
- PeachHud: 53MB / 65MB total
- HexHud: 84MB / 90MB total
Xhud's materials folder is ~3.5MB, Xhud's total size is ~5MB. With similar levels of custom materials as all the above, excluding HexHud's more complex reliance on custom materials (included as an outlier).
When converting images into VTFs using VTFEdit, developers have a variety of different image data formats to select from for the Normal Format and Alpha Format. Which of these is used is based on whether there is alpha (transparency) present in the source image. For details on each image data format and guidelines on when each should be used, check out the Valve Developer Community wiki entry on VTFs.
I'll quickly run through some of the compression methods here, along with their resulting file size (using the dneg_images_v3 killfeed file as sample).
-
512x1024 Source .png: 174 KB | .tga: 2049 KB (I tested both and got the same results, so source file format likely doesn't matter).
.png is a lossless compression format and .tga is an uncompressed image format. There should be no quality difference between these. - DXT5: 513 KB - Compressed file with 8-bit alpha. Good general-purpose format as it is file-size efficient and supports full color and transparency, the Alpha Format default for this reason.
-
DXT3: 513 KB - Interesting alternative to DXT5 as its essentially the same except 4-bit alpha, so it could be more efficient. However, that does not seem to be the case, so just follow the VDC guidelines and use DXT5 instead.
Note: Anecdotal evidence from JarateKing suggests that DXT3 may handle sharp changes in transparency better than DXT5, which handles gradual transparency changes better than DXT3. - DXT1: 257 KB - Compressed file, but no alpha. Useful for TOTALLY non-transparent images, and is the Normal Format default for this reason.
-
DXT1_ONEBITALPHA: 257 KB - Compressed file with binary alpha channel.
Note: Doesn't seem to work in TF2. - BGRA8888 / ABGR8888: 2049 KB - In HUDs these two are interchangeable. Both result in uncompressed file with 8-bit alpha. Could be desirable for extremely high quality images with full transparency, though I don't know of a real case of this being practical.
- BGRA888: 1537 KB - Uncompressed file with no alpha. Could be useful for high quality images with no transparency, such as menu backgrounds.
- BGRA5551 / BGRX5551: 1025 KB - Uncompressed file with 5-bit color channels (32 steps vs. 8-bit=256 steps) and binary alpha channel. So Sort of like an uncompressed equivalent of DXT1_ONEBITALPHA.
- BGRA4444: 1025 KB - Uncompressed file with 4-bit color channels and a 4-bit alpha channel (16 steps). Desirable if you want uncompressed detail but don't mind losing some color depth.
-
BGR565: 1025 KB - Uncompressed file with no alpha channel, interestingly allocates 5-bits to red and blue channels (32 steps) and 6-bits to green (64 steps). Sounds really strange, but it is actually conceptually similar to the distribution of color receptors in human eyes.
Note: Doesn't seem to work in TF2. - IA88: 1025 KB - Grayscale uncompressed file with 8-bit alpha. Useful if quality and transparency are really important but an image is black and white.
- I8: 512 KB - Grayscale uncompressed file with no alpha. Useful for high quality opaque images, maybe like a black and white menu background.
- A8: 512 KB - Uncompressed file with no color channels (color defaults to black) and an 8-bit alpha channel. Useful for transparent viewmodel VTFs as it stores no unnecessary information and an uncompressed 1x1 image is more compact than the minimum size compressed file (4x4).
- RGBA16161616/F: 4097 KB - HDR file, basically the opposite of compression. Useless in HUDs and takes an absurd amount of file space. Please do not use this.
Using the right compression method or image format for the task can reduce the size of a material with no perceivable loss in quality. For example, it would be pointless to use BGRA888 for a black and white image and would double the file size of said image. Meanwhile using DXT1 on an icon with complex transparency would result in an unusable material.
An actual example of misused image format would be the black and white killfeed icons present in many HUDs, including HypnotizeHud, HexHud, and PeachHud. These all use ABGR8888 image formats and as such, the 6 killfeed files take up 13.3 MB, while the killfeed icons contained in TF2 (that these files are edit from) use DXT5 image compression and take up only 2.5 MB across 6 files.
Pixel density is essentially a combination of the resolution a material is, as well as how big it is displayed. This is important because at a certain point increasing pixel density becomes useless. Trying to determine where to draw the line for this can lead to some deep rabbit holes, so here is the conclusion that I have come to based off various sources:
Most famously, Steve Jobs stated that the human eye is not able to perceive greater than 300 pixels per inch (PPI) when the screen is viewed from 10-12 inches away. This a fairly substantial over-simplification, but consider that the minimum recommended viewing distance for computer monitors is 20 inches, and that if it is good enough for Apple, it is probably good enough for HUD developers. Another thing to consider is that going beyond the pixel density of the screen the user is viewing on isn't wildly beneficial. An 8K-resolution monitor has a pixel density of ~366 PPI. So once again, 300 PPI +/- 100 PPI should be more than adequate for HUD developers.
Figure out how big you want an image or material to display on the screen (consider 27 inch monitors and larger), then multiply that by 300 and round to the nearest power of 2, and that is the resolution of your image.
So for example if I wanted my control point icons to take up 0.75x0.75 inches on the user's screen: 0.75 * 300 = 225
. So a resolution of 256x256 is adequate for my control point icons.
If you want to put a bit more thought into squeezing out every bit of file size optimization possible, then you can also consider a few additional factors and try lowering resolution accordingly:
- Level of Detail - A single-color image has no detail and as such having any resolution beyond 1x1 is unnecessary (Note the lowest I've gotten to work is 4x4). Meanwhile, high-detail images with complex curves or sharp lines will need a higher resolution.
- Prevalence on Screen - Human peripheral vision is incredibly poor quality, for example: if you extend your arm and focus on the tip of your thumb, only your thumbnail will be clearly in focus. As such, things that are intended to be viewed outside of your primary cone of vision, or are glanced at briefly, will generally be able to get away with lower resolutions.
- Contrast - Low contrast images will hide the boundaries between pixels better, and can allow for lower resolutions. This can be low color contrast, luminance contrast, or alpha contrast.
Removing lines of text from files isn't the most immediate way to see file size improvements, but removing 1000 instances of 10-byte lines across 100 files comes out to around 1 MB. So it can certainly add up but it is a low return on investment.
- AutoResize - Deprecated parameter.
- PinCorner - Deprecated parameter.
- TabPosition - Controls the order of where something is listed in the vgui_drawtree.
- DullText - "Determines if text should be displayed in a dull manner."
- BrightText - "Determines if text should be displayed in a bright manner."
- Default - Can be used on one button per screen to determine if pressing space or enter will trigger said element.
-
xpos / ypos / zpos - These will default to 0 if removed (most of the time), so if something was located at
xpos 0
andypos 0
I would opt to remove these. - PaintBackgroundType - This will default to 0 if removed (most of the time), so I would opt to remove this preferentially.
- TextAlignment + Wrap / CenterWrap - "Wrap" forces text to be West-aligned and "CenterWrap" forces text to be center-aligned, so when either is used "TextAlignment" can be cut.
- Entire elements - Sometimes entire elements can be deleted instead of resorting to moving them out of the render area. This can also help reduce the number of things the game needs to load and can help with load times or stutters on particular screens.
- %keywords - Used to help with finding map materials in Hammer map editor, not custom HUDs.
- $no_fullbright - Custom UI materials don't use lighting. Even if they did you would want fullbright to reduce unnecessary lighting calculations.
- $nolod - Tells the game not to use lower quality versions of a material when appropriate. You aren't making lower LOD versions of your materials so this does nothing (for custom materials and a majority of UI elements).