This is a common problem with very subtle gradients. The problem is that the image is displayed with 8 bits per component and this is not quite enough precision to make a gradient that is smooth to the eye under these conditions.
However, the underlying calculations being done in the shader are at higher precision (e.g. float = 24 effective bits of mantissa), so you can apply dithering to improve the appearance of the image.
You can do this by adding a slight amount of random noise to the value of each pixel in the shader. The noise can come from a texture, filled with random grayscale values in [0, 1] and mapped 1:1 to screen pixels. In the shader you remap this to the range [−0.5/255, 0.5/255] and add it to the output color.
Here's a Shadertoy demonstrating this. The left side has no dithering; the right side uses the procedure just described. As you can see, the banding vanishes on the right.
Dithering effectively allows you to represent intermediate values between 8-bit integer levels. For instance, an area that the shader computes as 82.3 (out of 255) would normally be uniformly rounded down to 82, but with dithering it will come out as a random mix with 70% of the pixels set to 82, and 30% set to 83. The eye averages over this very slight, high-frequency noise and it becomes practically invisible.