WebGL: Smooth Edges on Transparent Canvases
For a client project I needed to draw text on a transparent
WebGL canvas, which was overlaying a video playing in the background of the page.
After having a hard time with some of the more elaborate
Three.js based examples, I was able to quickly gain an initial understanding of the underlying plumbing when studying this WebGL-from-Scratch example.
The effect came together quickly and looked great, but unfortunately it didn’t render the same across all browsers. In Safari the partially transparent edges of the text where leading to while artifacts, as to can see here around the highlighted arc of the letter
At first I thought the
alpha property of the
contextAttributes hadn’t been honored, but when switching to a partially transparent font I would be able to see through the letters just fine.
Since I was already investigating the context properties, I tried my hand at the next one that could be related related to the transparency issue:
Simply changing this from
true didn’t improve anything for me in Safari. That was not entirely unexpected, since I assumed that I would have to actually “pre-multiply” the alpha for the setting to work correctly.
I didn’t know how to actually do this, and whether or not this could even be done with information from the canvas alone (or whether it would require knowing what is underneath it), so I just implemented this first attempt in the shader:
vec4 pixel = texture2D(tex0, uv).xyzw; gl_FragColor = vec4(pixel.x * pixel.w, pixel.y * pixel.w, pixel.z * pixel.w, pixel.w);
Luckily that did indeed solve the white marks on the edges, which are now very smooth:
While the edges are now smooth across the 3 browser listed below, you can see that the rendering color differs across them:
Next, I’ll have to look into how not only to achieve smooth but also color correct renderings.