ThreeJS 纹理从远处看时像素化 [英] ThreeJS Texture is pixelated when seen from distance

查看:51
本文介绍了ThreeJS 纹理从远处看时像素化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在玩 webGL 和 ThreeJS,然后我遇到了以下问题:

从远处看时,带有大图像的纹理会变得像素化.

检查示例:http://jsfiddle.net/4qTR3/1/>

代码如下:

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);场景.添加(光);var light2 = new THREE.AmbientLight(0x444444);场景添加(light2);var renderer = new THREE.WebGLRenderer({抗锯齿:真});renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);var geometry = new THREE.PlaneGeometry(500, 500, 10, 10);//我在我的项目中使用了不同的纹理var texture = new THREE.ImageUtils.loadTexture(TEST_IMAGE);var textureBack = new THREE.ImageUtils.loadTexture(TEST_IMAGE);textureBack.anisotropy = renderer.getMaxAnisotropy();纹理.各向异性 = renderer.getMaxAnisotropy();//过滤器纹理.magFilter = THREE.NearestFilter;texture.minFilter = THREE.LinearMipMapLinearFilter;textureBack.magFilter = THREE.NearestFilter;textureBack.minFilter = THREE.LinearMipMapLinearFilter;var 材料 = [新的 THREE.MeshLambertMaterial({透明:真实,地图:纹理,侧面:三.FrontSide}),新的 THREE.MeshLambertMaterial({透明:真实,地图:纹理返回,侧面:三.BackSide})];for (var i = 0, len = geometry.faces.length; i < len; i++) {var face = geometry.faces[i].clone();face.materialIndex = 1;几何.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;场景添加(平面对象);相机.位置.z = 1000;(函数渲染(){请求动画帧(渲染);planeObject.rotation.y += 0.02;renderer.render(场景,相机);})();

如果纹理的图像中有文字,文字会变得非常像素化,质量很差.

我该如何解决这个问题?

解决方案

为了不像素化,您需要使用 mips,但 WebGL 无法为非 2 次幂的纹理生成 mips.您的纹理是 800x533,它们都不是 2 的幂.

几个选项

1) 将图片离线缩放到 2 的幂,如 512x512 或 1024x512

2) 在制作纹理之前在运行时缩放图片.

自己加载图像,加载后制作一个 2 次幂的画布.调用 drawImage(img, 0, 0, canvas.width, canvas.height) 将图像缩放到画布中.然后将画布加载到纹理中.

您可能还想将 mag 过滤从 NearestFilter 更改为 LinearFilter.

注意:(1) 是更好的选择.(2) 在用户机器上花费时间,使用更多内存,并且您无法保证缩放的质量.

此处示例.

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?

解决方案

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.

这篇关于ThreeJS 纹理从远处看时像素化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆