22
\$\begingroup\$

Let's say I want to render a square; its texture is "square.png."

Is it easier for the computer to render it if the texture is just a plain color?

And what about if it is a very noisy texture with completely random colors here and there?

Or what if that texture is noisy in the sense that every pixel in it is different from one to another, but only by a tiny bit?

\$\endgroup\$
39
\$\begingroup\$

Like most things in game development, and especially in game graphics, the answer is "it depends"

Texture Size

The resolution of your texture can have an impact on rendering speed. The more pixels it contains, the more raw data there is to upload to the GPU, and the less of the texture we can fit in cache at a time, so the shader might hit more pauses while it waits for the right part of the texture to get pulled into cache.

Using mipmapping can reduce the impact of this. With mipmaps, we store a chain of downsized versions of the texture, which at first sounds like even more memory to schlep around. But it lets us read from the smaller versions when the texture is displayed at a small size on the screen (like a distant object in perspective), so our samples make better use of the texture cache, rather than jumping all over. This also reduces aliasing.

Texture Detail

The content of your textures doesn't have an impact on rendering efficiency most of the time.

A colour is just a bunch of numbers as far as the GPU is concerned, so it doesn't care much what those numbers are, it just funnels them through its math the same way. It doesn't do anything fancy like remembering "Oh, I've seen a pixel in this green before, I'll just re-use the same output I calculated last time I saw this input" so whether your texture is all one colour or random sparkles, your GPU is doing the same work.

Unlike formats like PNG & JPG, which compress more efficiently in predictable areas of the image, and eat up more bits in complex regions, GPU texture formats like BTC, ETC, PVRTC, or even raw RGBA use a fixed number of bits per block of pixels. So making your texture more or less detailed while keeping the same compression format won't change its data size or impact data transfer and cache-related efficiency.

But, if you use a particular kind of detail that your previous compression doesn't preserve well, you might be forced to change your whole image to use a different format, which could again change its data size.

Shader Branching & Indirection

Here's the biggest asterisk in the situation: you might be using this texture colour input to make decisions, like an if() branch. Here, detail matters for speed.

GPU shading units work on blocks of pixels in batches, running the same instructions in parallel on multiple streams of data. So when some pixels in the block take one branch of the if and other pixels take the other, the whole batch has to go through both branches (masking out the results that don't apply to one set of pixels or the other)

If your input changes in a smooth/predictable way, then you'll likely have many blocks that only need to take a single branch, and these both-branch cases will be limited to narrow bands around the transition border. But if your input is random-ish, we'd expect most blocks to take both branches and slow down the rendering.

This can also happen if you're using one texture to control lookups into a second texture, like a distortion or index map. If the first texture jumps around randomly, then we'll be sampling from scattered, random-ish spots of the second texture, making less consistent use of our texture cache and waiting longer to get the data we need, on average.


So, overall: no, the content of the texture doesn't have much impact on rendering speed, except for the cases when it does. ;)

\$\endgroup\$
  • \$\begingroup\$ Low-res textures (think Minecraft) would be more likely to load texels for adjacent pixels into the cache when a particular texel is loaded into the cache, right? \$\endgroup\$ – immibis Mar 14 '18 at 19:33
  • 6
    \$\begingroup\$ @immibis Minecraft has tiny textures. The default is just 16x16, which fits so easily into the texture cache of each core that it's not even funny :D And yes, most texture samples will be to the same texel, unless you're very far away from the block. This is especially true if you take the screen subdivision into account - if you're reasonably close, the whole batch for a given core might map to the same texel :D A simpler GPU would probably work better for such low-definition texturing - I suspect a lot of effort is wasted on optimisations that don't help anything for Minecraft. \$\endgroup\$ – Luaan Mar 14 '18 at 19:58
  • 1
    \$\begingroup\$ Side note: The "uses the same number of bytes per pixel" is actually key to some of the speed hacks that graphics code uses. If you were to try to use PNG internally, or even something like UTF-8 with a variable pixel size, to get to the nth pixel, you'd have to go through every single pixel before it. With a constant pixel byte width, it's just start_of_buffer + width * n, which is much faster, especially for large n. \$\endgroup\$ – Nic Hartley Mar 14 '18 at 21:39
  • \$\begingroup\$ @Luaan I mean that even when you are far away from the block, when it fetches one texel (whichever one is first) it should pull some adjacent ones into the cache as well. \$\endgroup\$ – immibis Mar 14 '18 at 22:30
  • 4
    \$\begingroup\$ That's the case I talk about above with mipmapping. To avoid having our samples skip all around the texture leaving big gaps between with little to no cache reuse, we store a 512x512 version and a 256x256 version and.... all the way down to 1x1 sometimes. So when drawing the 1024x1024 texture at 16x16, most games will actually be reading from the 16x16 mip, and it performs similar to the 16x16 Minecraft case in terms of cache efficiency. This also reduces sparkly aliasing artifacts from downsampling. \$\endgroup\$ – DMGregory Mar 14 '18 at 22:41
1
\$\begingroup\$

Along with DMGregory's excellent answer above, there is, perhaps, one case where the complexity of a "texture" can affect the rendering performance and that is where the results of a previous render are used as a source in a subsequent one, e.g. shadow maps/reflections/environment maps.

Some modern hardware may apply lossless compression to these buffers: for example PowerVR has PVRIC, AMD, Delta Colour Compression, and ARM has something similar. The aim of these compression techniques is to reduce overall bandwidth which, in turn, can improve rendering performance.

The simpler the data, be it depth or colour (integer or floating-point), the better these schemes will work. Of course, I wouldn't suggest deliberately simplifying your rendering output just for these to function better, but avoiding using noisy data might help in some circumstances.

Also, doing sparse sampling of frame/depth buffers which use these schemes, in a vain attempt to lower bandwidth, won't help because they are very likely to be block based.

Further you might find these two SE Computer Graphics questions and answers of interest:

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.