Bug with WebGL texImage2D

Description of the issue:
While using WebGL for a recent project of mine, I discovered that WebGL texImage2D and texSubImage2D generate unwanted noise in Brave, but only when loaded from non-localhost domains (i.e., it works if I download / run the html file directly).

The noise seems to be some type of lost precision in dark areas of the image and appears only under high contrast, but it is vital that this information persist since I’m utilizing the texture for passing application-specific, non-color data to the graphics card (very common in OpenGL projects).

My guess is, this is due to something specific in the way Brave handles WebGL to prevent WebGL ‘fingerprinting’ / tracking, which is why it works fine via localhost.

Steps to Reproduce:
Minimum example:
Run the following code as an HTML file right from your computer, and it will work fine (the second image below).
Run it from a webhost, however (from some non-local domain), and it appears to experience lots of noise in dark areas (the first image below).

<!DOCTYPE html>
<html>
	<body>
		<canvas id="canvas" width="512" height="512"></canvas>
		<script type="text/javascript">

			var canvas = document.getElementById('canvas'),
				gl = canvas.getContext('webgl'),
				vsh = gl.createShader(gl.VERTEX_SHADER),
				fsh = gl.createShader(gl.FRAGMENT_SHADER),
				prog = gl.createProgram(),
				rect = gl.createBuffer(),
				tex = gl.createTexture();

			gl.shaderSource(vsh,`
				precision mediump float;
				precision mediump int;

				attribute vec2 pos;

				varying vec2 point;

				void main() {
					gl_Position = vec4(pos, 0.0, 1.0);
					point = pos;
				}
			`);
			gl.compileShader(vsh);

			gl.shaderSource(fsh,`
				precision mediump float;
				precision mediump int;

				uniform sampler2D tex;

				varying vec2 point;

				void main() {
					vec4 color = texture2D(tex, point * vec2(0.5,-0.5) + vec2(0.5)) * 128.0;
					gl_FragColor = clamp(color, 0.0, 1.0);
				}
			`);
			gl.compileShader(fsh);

			gl.attachShader(prog, vsh);
			gl.attachShader(prog, fsh);
			gl.linkProgram(prog);

			gl.useProgram(prog);

			var progTex = gl.getUniformLocation(prog, 'tex'),
				progPos = gl.getAttribLocation(prog, 'pos');

			gl.bindBuffer(gl.ARRAY_BUFFER, rect);
			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
				-1,-1, 1,-1, 1,1, -1,1,
			]), gl.STATIC_DRAW);

			gl.enableVertexAttribArray(progPos);
			gl.vertexAttribPointer(
				progPos, // location ('pos' attribute)
				2, // components
				gl.FLOAT, // type
				false, // normalize
				0, // stride
				0 // offset
			);

			// important part:
			var render = document.createElement('canvas'),
				width = render.width = 64,
				height = render.height = 64,
				ctx = render.getContext('2d');
			ctx.fillStyle = 'black';
			ctx.fillRect(-1,-1,width+2,height+2);

			var pixels = ctx.getImageData(0,0,width,height);
			for(let i=5; i<60; i++) {
				// (5,5) -> (59,59)
				pixels.data[(i + i*width)*4] = i % 2 + 1;
			}
			ctx.putImageData(pixels, 0,0);

			gl.activeTexture(gl.TEXTURE0);
			gl.bindTexture(gl.TEXTURE_2D, tex);
			gl.texImage2D(
				gl.TEXTURE_2D, // target
				0, // mip level
				gl.RGBA, // internal format
				gl.RGBA, // format
				gl.UNSIGNED_BYTE, // type
				render // data
			);
			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);

			for(let i=5; i<30; i++) {
				// (5,30) -> (34,59)
				pixels.data[(i + (i+30)*width)*4] = i % 2 + 1;
			}
			ctx.putImageData(pixels, 0,0);
			var subpixels = ctx.getImageData(5,30, 30,30);

			gl.texSubImage2D(
				gl.TEXTURE_2D, // target
				0, // mip level
				5,30, // offset
				gl.RGBA, // format
				gl.UNSIGNED_BYTE, // type
				subpixels // pixels
			);

			gl.uniform1i(progTex, 0);

			gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);

		</script>
	</body>
</html>

Actual Result (gifs and screenshots are welcome!):

Expected result:

Reproduces how often:
On my computer at least. I’m unable to test other at this time.

Operating System and Brave Version(See the About Brave page in the main menu):
OS: Windows 10, 21H2
GPU: Intel(R) Iris(R) Xe Graphics
Brave Version 1.39.122 Chromium: 102.0.5005.115 (Official Build) (64-bit)

Additional Information:
This may be related to my graphics card, but it cannot be an issue with my graphics card since it works perfectly when open right from my computer. Brave is capable of rendering it properly, but simply does something differently when rendering it from a non-localhost domain.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.