ThreeJS 纹理从远处看时像素化 [英] ThreeJS Texture is pixelated when seen from distance
问题描述
我在玩 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.
这篇关于ThreeJS 纹理从远处看时像素化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!