goto:    mapping Links    Tutorials

Mapping help Tutorials for Half-Life & Mods

Texture dimensions vs. appearance, memory, and r_speeds

Texture dimensions have a significant effect on the appearance of the texture, the memory used by textures, and in a minor way on r_speeds. All compiling instructions refer to Zoner's & Merle's compiling tools.

General Rule of Thumb: Use (or make) a texture smaller than the brush (or the same size) and scale the texture upwards to fit. Use only textures with these edge dimentions: 16, 32, 64, 128, 256.


For the best looking textures, you should stick to "the powers of 2" dimensions. Those "powers of 2" are: 2, 4, 8, 16, 32, 64, 128, 256.

(Note 1: #s 2, 4, 8 cannot be used because they are smaller than 16. I just gave them to show the series.)
(Note 2: #512 can be used, but it should only be used with one of the others, not in a 512x512 format - unless you are prepared to lose some players. Anyone in software mode or with a poor video card will not be able to render 512x512 textures. See Taylor's note below.)

The reason these sizes are preferred, is that the rendering engine does not change them, so they stay sharp. If you have a between size (base 16 size), for example 48x96, then the engine resamples at 32x64, aliases and resizes to use. This results in a loss of texture quality, and maybe crosshatching. So while other sizes are legal, "the powers of 2" are the best to use.

(NOTE: With gl_round_down 0 somewhere in your autoexec.cfg, config.cfg or similar, the engine rounds up sometimes. Nearest-neighbour sampling, so kind of lumpy, but much better than the blurry textures. However, the engine is still resampling, which it does NOT do with "the powers of 2" sized textures! Furthermore, not everyone who plays your map will have that setting, or even open gl..)

What if you have a between size brush? You resize the ideal textured dimension, that is what. After all that is what the engine will do must make a choice then: to make an oversized "powers of 2" texture which when shrunk looks good an sharp, or a smaller "powers of 2" texture which when scaled up/stretched looks good an sharp - AND uses less memory.
Lets take a look at that next, and also later at the lag and scaling section under r_speeds.

Originally by Taylor
512x512 textures are bad, so bad I'll write bad in uppercase with bold and italics.     BAD

Software mode and older graphics cards (such as the Voodoo 3) do not like a texture with a lump size of over 65536. You work out the lump size by the simple equation x*y, examples are:

  • 256*256 = 65536 Fine.
  • 512*128 = 65536 Fine.
  • 1024*64 = 65536 (Should work, but it doesn't, stupid ratio anyway. )
  • 512*512 = 262144 (No, you idiot, what are you doing?!)

If Half-Life or OpenGL (depends on the drivers what happens) doesn't like the Texture Lump, it'll:

  • Draw it, and give slow down.
  • Draw it, and give heavy slow down, the sort that makes players scream and shout, and pull out hairs right to the roots so their head starts bleeding and running down their faces, blinding them and preventing them from playing (maybe).
  • Not draw it, giving the player a HOM (hall of mirrors) effect, which of course will allow them also to see into other area's of the map.

So to recap, 512*512 = BAD, you can have 512x128 textures and other simular combinations of sizes, as long as the lump size is under 65536, which can be worked out by x*y.

Memory required

Some mods are making a limit on total texture memory load in a level; because for software mode players, maps with a too large texture memory load crash and become unplayble. How does this relate to dimensions? The larger the dimensions the more memory required. 256x256 takes 4x the memory of 128x128. Thus you may want to make an oversized "powers of 2" texture that when shrunk looks sharper - but you have to decide if you can afford the memory. Also see lag and scaling below.

Besides using a smaller texture there are other ways to save memory. One is to use 2 textures in one. If you need a 48x96 texture to fit a planned brush, put it on a 64x128, and only use part of the space. in the remainder 16x128 side or the or 64x32 space you could place another texture. Then both of these textures would look sharp when their part was placed on a brush without resizing, and yet you would make maximum usage of the memory used. This would not work for tiling textures, of course.
Anyway, it takes a really big map with a lot of details to go over this texture memory load limit, for most maps do not worry about it!


There have been discussions about the 240/224 subdivide on faces to create wpolys, and how using a 224x224 or 240x240 texture scaled up to 256x256 can keep wpolys low with minimal stretching. That is true, a 224x224 or 240x240 size texture scaled up to fit a 256x256 brush will create less wpolys than a 256x256 texture unscaled.
HOWEVER texture quality suffers as mentioned above - the engine resamples at 128x128, aliases and resizes to use. This results in a loss of texture quality, and maybe crosshatching. You may as well start with a 128x128 texture of good quality - remember 128x128 stays sharp looking - and stretch that to fit 256x256. (Btw, the 240 subdivide is used by the engine when there is not tiling, the 224 is used with tiling textures.)
Moreover, rarely indeed will the few polys difference of using a 240/224 texture vs a 256 make or break a level's playability. If things are that tight, the whole map needs to be rethought.....

If you are facing the problem of minimizing wpolys in a wide open area, stretching/scaling 9x is about the limit of the engine, more causes problems and errors. If you stretch a 256x256 texture 9x then the 224 subdivide will also be stretched 9x = a wpoly of 2016x2016. That is about the maximum wpoly you can have - regardless of what texture size you use. 9x (224x224) = 2016x2016, 9x (128x128) = 2016x2016, 9x (16x16) = 2016x2016 subdivide/wpoly size. The only difference is how many times the smaller textures will tile within that 2016.
That is one of the vital things to realize. Texture sizes do not control the subdivide per se. A 16x16 will not make wpolys 16x16 if it is not stretched. Instead it will make the wpoly at the brush size or 224, whichever is smaller. It is texture stretching which stretches (or shrinks) the subdivide - not the texture size!

note: to get the full effect of the 2016x2016 on the ground, you will also have to increase the maxnodesize in BSP compile from the default 1024 to 2048. HLBSP -maxnodesize 2048 is the command you need. However, be aware that changing the maxnodesize for leafnodes on ALL maps is NOT a good thing. On smaller maps, or maps with lots of corridors and no large open space it may INCREASE your r_speeds and lag, because the leafnodes will "see" more wpolys. For such maps DECREASING maxnodesize from 1024 down to 512 can reduce wpolys, sometimes. One needs to experiment to find the best mode - but all this is for compile experts. Finally, the maxnodesize does not really affect walls much, so if you are building a skyscraper you can pretty much ignore it.

note2: the subdivide CAN be changed up from 240 to say 256. This will allow 1 wpoly for a 256x256 texture on a 256x256 brush face. The problem is that software video mode does NOT allow subdivide to be changed, so NO software video mode user can play your level. Also you cannot decrease subdivide below 240. Finally some compilers do not allow subdivide to be changed, and you will get a "bad surface extents" error during compile. But if you want to experiment, HLBSP -subdivide 256 is the command you need.

example of using the texture tool for scaling Note the 1.5 scaling, and the 128x128 texture size.

More on lag and scaling relating to patches

There is another matter you should be aware of. On older video cards like Voodoos, scaling down below 1.0 had worse effects for lag than you would expect from the additional wpolys. (example: voodoo3 didn't have hardware transformation and lighting.) Firebinder did some research and found that scaling down also affected the patches used by lighting up a level, so that fps (frames per second rate) dropped even when the wpoly count was not changing.
Therefore when using a small brush, it is better to use a small texture and scale up, than to scale down a larger one. Even with the same wpoly count, the down scale might lead to lag on some players with older video cards or who are still using software mode.

However, there is another way to deal with the problem besides only scaling up textures: HLRAD -notexscale. This stops the compiler from basing the patch sizes on the texture scale. But this -notexscale usually increases the number of patches in a map, as most maps have many walls scaled up 2x or 3x or even 9x to reduce r_speeds - as described above. So if you are shrinking textures/scaling down and having patches problems/lag in an area with an older video card/software mode, then experiment with -notextscale - but do not use it automaticly all the time.
Furthermore do not forget HLRAD -sparse can also help with too many patches, even if the compile will be slower.

BTW: You might think of shrinking textures down on purpose for more patches on a textures, hoping for better lighting. There are better ways to control patches:
HLRAD -texchop # and HLRAD -extra to control texture "light giving" patches sizes, (default TEXCHOP is 32x32 x texture scale, unless -notextscale is on, and default EXTRA is 1/2 texchop/16x16 respectively. But EXTRA may do more than just 1/2 the texchop!);
and HLRAD -chop # to control the size of general "lighted on" patches. (64x64 x texture scale is the CHOP default, unless -notextscale is on, in which case default is 64x64 only.) FYI: Chop larger than 96 generally looks poor.

The combination of HLRAD -notexscale -sparse -texchop 16 -extra -chop 32 can be especially handy for lighting a level extra fine, but will be a slow compile due to the many, many extra patches.

Null texture and R_speeds/lag

If you get Merle's compile tools, there is a special texture called NULL that works with them. This texture removes the faces it is on when it is compiled. Since that face is now gone, r_speeds and lag are lower because the game engine no longer has to render that face. But that also means you cannot use NULL any place a player can see, because you do not want a 'hall of mirrors' error.
So you are limited to using NULL on the backside of those brushes of which the player cannot see the other side. Null is of limited use, therefore, and must be used carefully; yet it still has some valuable use, and does lower r_speeds and patches a little in a map.
Repeating: NULL only works with the newer versions of Merle's compile tools, and with no other compiler.

FYI: Why is the max subdivide size 240?

Originally by Rhett on the ERC forums.

Why is the max subdivide size 240, and not 256? Well, there is a very good reason for this.

In software mode the world is split up into squares. As you move closer to a surface you see the squares get bigger. Quality suffers.

In hardware mode, no matter how close you are to a surface it will always appear smooth. This smooth transition between pixel values is done by sampling the neighbourhood pixels and calculating an average at each point.

The problem is what happens at the texture edges. The hardware uses a wrap-around method, so that the left edge pixels are influenced by the values of the right edge pixles, and vice versa. This explains the 'dirty border effect' you sometimes see at corners/edges in hardware mode, because left and right border pixels have no relation to eachother, but are still used in the same computation.

It is to get rid of this effect that the subdivide size is 240. It means that you can have a 256x256 texture with an unused 8 pixel border all around. This left border area will contain the right border values and vice versa (same for the top and bottom edges).

Of course, those that make textures tile, where the texture itself has border values that are the same on each side, will find the extra 8 pixel border unnecessary. But if you use non-tileable textures that must fit together (like a large surface covered with a set of textures that all come from the same image), then this unused 8 pixel border is very useful. It will contain the overlapping values.

(That 8 pixel border is problably also the reason why 16 is the minimum texture border size.)

FYI: Why tiling makes wpolys occur at (224 x texture scale) instead of (240 x texture scale)?

Originally by Merl on the ERC forums.

From the code in the zhlt source the formulae for subdivisions basically boils down to the following line of code:

plane.dist = (mins + g_subdivide_size - 16) / v;

that is, basically, the subdivide size minus 16. Do the math on 240 - 16, and you get 224.

(Zoner is also reported to have said that too many 240x240 wpolys may cause some wpolys to not appear, later in that same thread.)

FYI: Can the max subdivide size be changed?

From Merle in version 1.7 of his compile tools: Increased maximum subdivide value in hlbsp to 512. You may now specify a value using the -subdivide parameter other than 240. WARNING: Doing so may cause problems in software mode. If in doubt, leave at the failsafe default value of 240.

(So if you intend for any player who ever uses software mode to be able play your map, do not change the subdivide!)

webpage copyright (c) March 2003 Tommy of Escondido