I desperately seek for somewhere to discuss this strange bug i found in firefox. But it seem hard to meet some mozilla crew.
Context is very simple: WebGL 2.0, drawing text using the well known fontmap technic with point-sprite.
One image is better than 1000 words:
On the right Chromium, all is ok, on the left Firefox... and uhhggh ?!
Questions:
Why the text is yellow in Firefox despite the fact it should be white ? ?
Why the text have strange black pixels in firefox ?
This seems to be a kind of "sharpen" filter... but WHY ?
Some details :
This is exactly the same code for both browsers.
The fontmap texture is generated using an "off-screen" canvas, this is RGBA with RGB all white and characteres printed in alpha channel. I verified the generated picture on both browsers, they are not exactly the same, but all appear OK (no strange pixel nor black border, etc...), the problem seem to be not here
The WebGL texture is RGBA/RGBA/UNSIGNED BYTE (as usual), MIN and MAG filter to NEAREST, no mipmaps, with WARP S/T Clamp to edge (but this change nothing, so it doesn't matter)
The generated texture is NPOT, but i don't think the problem is here.
The Blend equation used to render the text is (the usual) SRC_ALPHA, ONE_MINUS_SRC_ALPHA
I tested with the blend equestion SRC_ALPHA, ONE and in this case Firefox acts correctly (but additive blending is not what i want !).
Firefox Version: 55.0.2 (64 bits) Mozilla Firefox for Ubuntu
Chromium version: 60.0.3112.113 Built on Ubuntu, running on Ubuntu 16.04 (64 bits)
Here is the fragment shader (using Point-Sprite to draw each char):
precision highp float;
in float chr_c;
uniform vec4 material_col;
uniform sampler2D spl2d_col;
vec2 chr_u;
out vec4 fragColor;
void main(void) {
chr_u.x = (gl_PointCoord.x + mod(chr_c, 48.0)) * 0.020833333;
chr_u.y = (gl_PointCoord.y + floor(chr_c / 48.0)) * 0.020833333;
fragColor = texture(spl2d_col, chr_u) * material_col;
}
Here is the code used to generate the fontmap texture:
var i, s, x, y, m, w, h, a, o, mx, cv, ct;
mx = c*c; // 'c' is rows/columns count, (here: 48 rows * 48 cols)
cv = document.createElement('canvas');
ct = cv.getContext('2d');
x = 0;
y = 0;
m = 65535;
// determins the size for cells according chars size
for(i = 0; i < mx; i++) {
s = String.fromCharCode(i);
w = ct.measureText(s).width;
h = ct.measureText(s).height;
if(x < w) x = w;
if(y < h) y = h;
if(y < m && (y > 0)) m = y;
}
var r = Math.ceil((y+(y-m)>x)?y+(y-m):x);
w = r * c;
h = r * c;
cv.width = w;
cv.height = h;
ct.fillStyle = 'rgba(255,255,255,0.0)';
ct.fillRect(0, 0, w, h);
ct.font = 'normal ' + p + 'pt ' + f;
ct.fillStyle = 'rgba(255,255,255,1.0)';
ct.textAlign = 'left';
ct.textBaseline = 'top';
for(i = 0; i < mx; i++) {
a = Math.floor(i % c); // cell Easting (Abscisse a = X)
o = Math.floor(i / c); // cell Northing (Ordonnée o = y)
ct.fillText(String.fromCharCode(i), (a*r)+3, (o*r)+2);
}
var gl = this._gl;
this._blank_fnt = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this._blank_fnt);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, ct.getImageData(0,0,w,h));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);
cv.remove();
here is the (simplified) code used to draw the text:
gl.enable(gl.BLEND);
gl.depthMask(gl.TRUE);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.useProgram(le_shader);
gl.activeTexture(gl.TEXTURE0);
gl.uniformMatrix4fv(le_uniform1, le_view.matrix);
gl.uniformMatrix4fv(le_uniform2, le_transform.matrix);
gl.uniform4fv(le_uniform3, le_text.color);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.bindTexture(gl.TEXTURE_2D, this._blank_fnt);
gl.bindVertexArray(le_text.vao);
gl.drawArrays(gl.POINTS, 0, le_text.count);