title: Alpha gradients not smooth in WebGL when using premultiplied alpha
body: <p>I've got a LibGDX game with cartoon clouds with a smooth gradient. There are other examples of gradients in the game that have a similar issue, but the clouds are the most obvious example. They look fine in Android, on iOS and on the Desktop version of the game, but on the WebGL version the gradients are not drawn as smooth. It only appears to be alpha gradients that have the problem. Other gradients look ok.</p>
  
  <p>I've tried on 3 different devices in Chrome and IE, and all 3 produce the same results. You can find a test of the HTML5 version here.</p>
  
  <p><a href="https://wordbuzzhtml5.appspot.com/canvas/" rel="nofollow noreferrer">https://wordbuzzhtml5.appspot.com/canvas/</a></p>
  
  <p>I've added an example IntelliJ project on github here</p>
  
  <p><a href="https://github.com/WillCalderwood/CloudTest" rel="nofollow noreferrer">https://github.com/WillCalderwood/CloudTest</a></p>
  
  <p>If you have intelliJ, clone that project, open the build.gradle file, press Alt-F12, type <code>gradlew html:superdev</code> and then browse to <a href="http://localhost:8080/html/" rel="nofollow noreferrer">http://localhost:8080/html/</a> </p>
  
  <p>The critical code is <code>render()</code> <a href="https://github.com/WillCalderwood/CloudTest/blob/master/core/src/com/mygdx/game/MyGdxGame.java" rel="nofollow noreferrer">here</a></p>
  
  <p>The bottom image here is the desktop version, the top is the WebGL version, both running on the same hardware.</p>
  
  <p><img src="https://i.stack.imgur.com/ui8rC.png" alt="enter image description here"></p>
  
  <p>There's nothing clever going on with the drawing. It's just a call to</p>
  
  <pre><code>    spriteBatch.draw(texture, getLeft(), getBottom(), getWidth(), getHeight());
  </code></pre>
  
  <p>I'm using the default shader, textures packed with premultiplied alpha with the blend function set as</p>
  
  <pre><code>    spriteBatch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
  </code></pre>
  
  <p>This is the actual image, although alpha not premultiplied as that's done by my packer.</p>
  
  <p><img src="https://i.stack.imgur.com/Bk1s9.png" alt="enter image description here"></p>
  
  <p>Does anyone know a possible reason for this and how I might resolve it?</p>
  
  <p><strong>Update</strong></p>
  
  <p>This only appears to happen when using the blending mode <code>GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA</code></p>
  
  <p><strong>Another Update</strong></p>
  
  <p>I've tried changing the whole game to use non-premultiplied alpha textures. I use Texture Packer which can help fix the halo issues that often occur with non-premultiplied alpha. All this works fine in the Android and Desktop version. In the WebGL version, while I get smooth gradients, I get still get a small halo effect, so I can't use this as a solution either.</p>
  
  <p><strong>And another update</strong></p>
  
  <p>Here's a new image. Desktop version on the top, web version on the bottom. Blending mode <code>GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA</code> on the left and <code>GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA</code> on the right</p>
  
  <p><a href="https://i.stack.imgur.com/vrPQx.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vrPQx.png" alt="enter image description here"></a></p>
  
  <p>Here's a zoomed version of the bottom left image above with increased contrast to show the issue.</p>
  
  <p><a href="https://i.stack.imgur.com/gv3si.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/gv3si.png" alt="enter image description here"></a></p>
  
  <p>I've also done a lot of playing with the fragment shader to try and work out what's happening. If I set</p>
  
  <pre><code>gl_FragColor = vec4(c.a, c.a, c.a, 1.0);
  </code></pre>
  
  <p>then the gradient is smooth, but if I set</p>
  
  <pre><code>gl_FragColor = vec4(c.r, c.r, c.r, 1.0);
  </code></pre>
  
  <p>Then I get banding. This points towards a precision issue I believe as the colour channels have been squeezed into the darker end of the spectrum by the pre-multiplication process.</p>