3
\$\begingroup\$

In an Android game, I have a gradient background that changes color over time. This was achieved by creating a 1x2 pixel texture in code, and stretching it over a large quad with bilinear filtering.

This all works fine in the editor, but as soon as it is viewed on an Android device, the banding is ridiculously noticeable and annoying.

Since this texture is generated in code, I cannot set the compression to "truecolor" like most other post suggest, nor can I tick the "Generate Mipmap" option.

Here is how the gradient look on the phone : enter image description here

Code to generate gradient (stripped of unimportant stuff):

Texture2D gradient;
MeshRenderer render;
Color HSV1, HSV2;
Color primaryColor, secondaryColor;

render = GetComponent<MeshRenderer>();

Update() {
    HSV1.x += 0.01F * Time.deltaTime;
    HSV2.x = HSV1.x;

    if (HSV1.x > 1)
        HSV1.x = HSV1.x - 1;

    if (HSV2.x > 1)
        HSV2.x = HSV2.x - 1;

    primaryColor = Color.HSVToRGB(HSV1.r, HSV1.g, HSV1.b + HSVdifferece);
    secondaryColor = Color.HSVToRGB(HSV2.r, HSV1.g - HSVdifferece, HSV1.b - HSVdifferece);

    gradient.SetPixel(0, 0, primaryColor);
    gradient.SetPixel(0, 1, secondaryColor);
    gradient.filterMode = FilterMode.Bilinear;
    gradient.Apply();

    render.material.SetTexture("_MainTex", rainbow);

}

The color banding is really obvious and annoying. How can I fix this?

\$\endgroup\$
  • \$\begingroup\$ can you please add some code so it'll be easier to help and work from there. thanks. \$\endgroup\$ – Daniel Netzer Jul 2 '16 at 8:44
  • \$\begingroup\$ Sure thing, added code. \$\endgroup\$ – eclmist Jul 2 '16 at 9:23
1
\$\begingroup\$

While this question is old, I'll leave a note here for anyone following on later:

Colour interpolation between adjacent texels is performed using fixed point math. The exact precision of this math isn't specified in the standard - desktop GPUs pretty much all use 24.8, but it wouldn't surprise me if mobile GPUs use even lower precision, which would account for the artifacts showing up only on the Android device.

This texture filtering is designed to help fill in gaps of a few pixels between texture samples when you get a bit too close to a wall in 3D games, for example - but it doesn't hold up as well when you try to stretch two texels to fill the entire screen.

The simple fix is to add a few more pixels to your gradient texture, so you're not leaning quite so hard on the interpolation texture filtering to generate all the intermediate colours you want. A 1x16 texture is still lightweight, and gives you about 15 times the number of intermediate colour values.

You could even skip the texture lookup outright and calculate your gradient in the shader, with full floating point precision if you so desire.

For extremely close colours like in the example image, you may also hit the precision limits of the back buffer, or the screen's rendering capabilities. Adding a slight dither to the gradient, by offsetting your lookups by a bias that varies per screen pixel, can help mask this by breaking up the sharp banding lines (graphics programs like Photoshop do this for their gradient fill tools).

\$\endgroup\$
0
\$\begingroup\$

Texture2D constructor has textureFormat and mipMap arguments. So create texture with options needed and set your pixels you want.

\$\endgroup\$
  • \$\begingroup\$ The constructor of Texture2D takes in a type of TextureFormat. To my knowledge, TextureFormat only contains compressed formats (ie: there is no TextureFormat.Truecolor). \$\endgroup\$ – eclmist Jul 5 '16 at 13:41
  • 1
    \$\begingroup\$ you should try to look at the documentation on that enum and search a bit on that topic RGBA32 is what you need or some other truecolor textureformat \$\endgroup\$ – Yevhen Jul 9 '16 at 15:42
  • \$\begingroup\$ Since the user's texture is 1x2, the dozen or so bands of colour we see in the screenshot can't be caused by texture compression. At worst, compression would change the accuracy of the two colour endpoints. What we're looking at instead is inaccuracy of colour interpolation. \$\endgroup\$ – DMGregory Dec 18 '16 at 16:40

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.