Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ThreeJS Texture is pixelated when seen from distance

Tags:

three.js

webgl

I was playing with webGL and ThreeJS, then I've got the following issue:

Textures with large images gets pixelated when seen from distance.

Check the example: http://jsfiddle.net/4qTR3/1/

Below is the code:


    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 10, 7000);

    var light = new THREE.PointLight(0xffffff);
    light.position.set(0, 150, 100);
    scene.add(light);

    var light2 = new THREE.AmbientLight(0x444444);
    scene.add(light2);

    var renderer = new THREE.WebGLRenderer({
        antialias: true
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    var geometry = new THREE.PlaneGeometry(500, 500, 10, 10);

    //I use different textures in my project
    var texture = new THREE.ImageUtils.loadTexture(TEST_IMAGE);
    var textureBack = new THREE.ImageUtils.loadTexture(TEST_IMAGE);

    textureBack.anisotropy = renderer.getMaxAnisotropy();
    texture.anisotropy = renderer.getMaxAnisotropy();

    //Filters
    texture.magFilter = THREE.NearestFilter;
    texture.minFilter = THREE.LinearMipMapLinearFilter;
    textureBack.magFilter = THREE.NearestFilter;
    textureBack.minFilter = THREE.LinearMipMapLinearFilter;

    var materials = [
    new THREE.MeshLambertMaterial({
        transparent: true,
        map: texture,
        side: THREE.FrontSide
    }),
    new THREE.MeshLambertMaterial({
        transparent: true,
        map: textureBack,
        side: THREE.BackSide
    })];

    for (var i = 0, len = geometry.faces.length; i < len; i++) {
        var face = geometry.faces[i].clone();
        face.materialIndex = 1;
        geometry.faces.push(face);
        geometry.faceVertexUvs[0].push(geometry.faceVertexUvs[0][i].slice(0));
    }

    planeObject = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));

    planeObject.overdraw = true;
    planeObject.position.z = -5000;

    scene.add(planeObject);

    camera.position.z = 1000;

    (function render() {
        requestAnimationFrame(render);
        planeObject.rotation.y += 0.02;
        renderer.render(scene, camera);
    })();

If the image of the texture has got text in it, the text becomes very pixelated with poor quality.

How can I fix this?

like image 699
DMF Avatar asked Dec 06 '22 05:12

DMF


1 Answers

In order to not get pixelated you need to use mips but WebGL can't generate mips for non-power-of-2 textures. Your texture is 800x533, neither of those is a power of 2.

a couple of options

1) Scale the picture offline to powers of 2 like 512x512 or 1024x512

2) Scale the picture at runtime before making a texture.

Load the image yourself, once loaded make a canvas that is power-of-2. call drawImage(img, 0, 0, canvas.width, canvas.height) to scale the image into the canvas. Then load the canvas into a texture.

You also probably want to change your mag filtering from NearestFilter to LinearFilter.

Note: (1) is the better option. (2) takes time on the user's machine, uses more memory, and you have no guarantee what the quality of the scaling will be.

Example here.

like image 154
gman Avatar answered Jan 08 '23 06:01

gman