Ad

Quality Differences Between HTML, Canvas And WebGL

- 1 answer

I want to draw an image in WebGL, but downscaled. When I don't scale it, then the image has a good quality, but if I scale it down then it has poor quality.

I read about 'Handling High DPI (Retina) displays in WebGL' from here: http://www.khronos.org/webgl/wiki/HandlingHighDPI and I tryed to do the same. My code in WebGL is:

        Initializations:

        var devicePixelRatio = window.devicePixelRatio || 1;

        gl.canvas.style.width = "800px";
        gl.canvas.style.height = "600px";

        canvas.width = Math.round(800 * devicePixelRatio);
        canvas.height = Math.round(600 * devicePixelRatio);


        For drawing:

        gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
        matrix = m3.scale(matrix, 28/800, 35/600); // matrix for scaling texture

        Textures:

        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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

But this didn't have the same quality like the HTML image. My code in HTML is:

        setTimeout(function() {

            var imagine = new Image();
            imagine.src = 'Tank.png';
            imagine.width = '28';
            imagine.height = '35';
            document.body.appendChild(imagine);

        }, 1000);

My code in canvas is:

        var imagine = new Image();
        imagine.src = 'Tank.png';
        imagine.width = '28';
        imagine.height = '35';
        imagine.onload = function() {
            context.drawImage(imagine, 0, 0, 28, 35);
        }
        context = canvas.getContext('2d');



The difference between quality of images is below ( quality: WebGL < Canvas < HTML)

WebGLCanvasHTML

I know that is not a very big difference, but I really want to show pictures at good quality. In HTML the picture is smoother. I observed that if I zoom in the Chrome browser, than the picture from HTML is increasing in quality, but the WebGL picture it remains at the same resolution and it will decrease quality. And if I refresh the page, to update the devicePixelRatio for WebGL, then the picture has better quality, but my browser is working slower at 500% zoom, I think because it makes the canvas bigger and it has to draw more. But in HTML, if I move the image at 500% zoom, there are not problems, the image is moving well and it has good quality.


In this situation - WebGL image rendering bad quality - the image is not scaled, but I need scaling down pictures.

And compared to this situation - canvas drawImage quality - I put the values as integers, in all three programs.



Final Question:

How can I draw images in webGL as in HTML at the same quality (not seeing that lines from those tracks) and to have good quality even the browser zoom in ? What other possibilities do I have to draw them ? What technology should I use ? I wanted to use WebGL because it has some features that the HTML doesn't have and I wanted to draw some things from scratch, like lines or points.


EDIT 1: This is the picture at the normal resolution.


Tank Picture


In this picture it seems that the lines of the tracks are not straight, but they are crossing. If you can look close to the images from Canvas and WebGL, the first lines of the tracks, first on left and first on right, they are straight. More, the picture with Canvas has more straight tracks, even the last ones. The last image of HTML has all tracks of the same shape.


I am sorry because I put very small pictures. It's because I need this scale and I need that pictures not to be bigger. If I would draw bigger pictures then the devicePixelRatio would make pictures to look much better, but I don't use the pictures at normal dimensions. In that way, the problem could have been solved by devicePixelRatio. For smaller dimensions this method with devicePixelRatio doesn't help me. That's why I am looking for another solution.

Ad

Answer

If you want your pictures to be drawn more smooth, then you could use mipmaps! Try to make the pictures to have both dimensions a power at 2 and after you can generate mipmaps, like this:

gl.generateMipmap(gl.TEXTURE_2D);

With mipmaps you can choose what WebGL does by setting the texture filtering for each texture. And if you want to your image to be smooth, then you have to change the texture filtering to be LINEAR_MIPMAP_LINEAR. So after you generate the mipmaps you have to write:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);

The pictures with the differences are below ( LINEAR vs LINEAR_MIPMAP_LINEAR ):

LINEARLINEAR_MIPMAP_LINEAR

In first picture the tracks are asymmetric, but the second picture is drawn smooth. I think that the second picture looks more like the HTML picture that you provided.


There is a great tutorial about WebGL Textures: https://webglfundamentals.org/webgl/lessons/webgl-3d-textures.html. There is written that this type of texture filtering is the slowest and it takes 33% more memory, so be aware of that!

Ad
source: stackoverflow.com
Ad