立方体贴图天空盒的三个.js 角是暗的

问题描述

我试图在three.js中制作带有白点(星星)的黑色天空盒。因为角落更远,角落里的点看起来更暗(透视使它们更小、更暗)。有没有办法让它更均匀,让角落不那么明显?

这是一个例子(相机正在观察一个角落):

// scene
var scene,camera,renderer;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.05,1000);
camera.position.z = -0.01;
renderer = new THREE.Webglrenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.setClearColor(0x000000,1);
document.body.appendChild(renderer.domElement);

// canvas with dots
var canvas,context,texture,geometry,mesh,material,x,y,s,dx,dy;
canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
context = canvas.getContext('2d');
context.fillStyle = 'white';
for (y = 0; y < 512; y += 8) {
    for (x = 0; x < 512; x += 8) {
        s = 1;
        context.fillRect(x,s);
    }
}

// cube with canvas texture 
var texture,mesh;
texture = new THREE.CanvasTexture(canvas);
material = new THREE.MeshBasicMaterial({map: texture,side: THREE.DoubleSide});
geometry = new THREE.BoxGeometry(100,100,100);
mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);

camera.lookAt(1,1,1);
renderer.render(scene,camera);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r125/three.js"></script>

当我生成点时,如果它们离画布中心更远,我可以使它们稍微大一点,例如,而不是 s = 1;我会用:

dx = (x - 512) / 512;
dy = (y - 512) / 512;
s = 1 + Math.sqrt(dx * dx + dy * dy) / 2;

但我宁愿有three.js解决方案,这样我就不必修改画布。角落里的点更密集不是问题,这个演示有均匀的点分布,使演示更简单,真实的代码不会在角落里出现更密集的点。

解决方法

这是一种视错觉。它并没有真正使角落变暗,但是随着纹理变得越来越小,纹理样本正在使用 lower resolution MipMaps。如果您有一个白色像素,周围有 7 个黑色像素,则较小比例的 MipMapping 将开始混合成大部分为黑色的纹理。

您可以通过使白点相对于其周围空间更大来最小化此问题。或者您可以使用 texture.minFilter = THREE.LinearFilter;NearestFilter 关闭 MipMapping,尽管这可能会给您带来不希望的、粗糙的外观。 See other Minification Filter options here

见下文,我使用的是 LinearFilter 和一个 2 像素的白色方块。它看起来不太好,但它说明了两种可能的解决方案:

// scene
var scene,camera,renderer;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.05,1000);
camera.position.z = -0.01;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.setClearColor(0x000000,1);
document.body.appendChild(renderer.domElement);

// canvas with dots
var canvas,context,texture,geometry,mesh,material,x,y,s,dx,dy;
canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
context = canvas.getContext('2d');
context.fillStyle = 'white';
for (y = 0; y < 512; y += 8) {
    for (x = 0; x < 512; x += 8) {
        s = 2;
        context.fillRect(x,s);
    }
}

// cube with canvas texture 
var texture,mesh;
texture = new THREE.CanvasTexture(canvas);
texture.minFilter = THREE.LinearFilter;
material = new THREE.MeshBasicMaterial({map: texture,side: THREE.DoubleSide});
geometry = new THREE.BoxGeometry(100,100,100);
mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);

camera.lookAt(1,1,1);
renderer.render(scene,camera);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r125/three.js"></script>