【发布时间】:2018-08-31 00:39:12
【问题描述】:
three.js 中的distance 设置与基于物理的光照相关是什么意思?
对于非基于物理的照明,distance 设置是灯光的影响线性淡出的设置。有效
lightAffect = 1 - min(1, distanceFromLight / distance)
我不太了解基于物理的照明,但在我看来,真正的灯光没有距离设置,它们只有功率输出(流明)和基于大气密度的衰减。 Three.js 有一个 power 设置和一个 decay 设置,尽管完全不清楚应该将 decay 设置为什么,因为文档实际上只是说将其设置为 2。
如果我想要基于物理的照明,我应该为基于物理的PointLight 设置distance 什么?
'use strict';
/* global dat */
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas: canvas});
renderer.physicallyCorrectLights = true;
const fov = 45;
const aspect = 2; // the canvas default
const zNear = 0.1;
const zFar = 100;
const camera = new THREE.PerspectiveCamera(fov, aspect, zNear, zFar);
camera.position.set(0, 10, 20);
camera.lookAt(0, 5, 0);
const scene = new THREE.Scene();
scene.background = new THREE.Color('black');
{
const planeSize = 40;
const planeGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize);
const planeMat = new THREE.MeshPhongMaterial({
color: '#A86',
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(planeGeo, planeMat);
mesh.rotation.x = Math.PI * -.5;
scene.add(mesh);
} {
const cubeSize = 4;
const cubeGeo = new THREE.BoxBufferGeometry(cubeSize, cubeSize, cubeSize);
const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
const mesh = new THREE.Mesh(cubeGeo, cubeMat);
mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
scene.add(mesh);
}
{
const sphereRadius = 3;
const sphereWidthDivisions = 32;
const sphereHeightDivisions = 16;
const sphereGeo = new THREE.SphereBufferGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
const mesh = new THREE.Mesh(sphereGeo, sphereMat);
mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
scene.add(mesh);
}
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.PointLight(color, intensity);
light.power = 800;
light.distance = 20;
light.position.set(0, 10, 5);
scene.add(light);
light.decay = 2;
const helper = new THREE.PointLightHelper(light);
scene.add(helper);
const onChange = () => {
helper.update();
render();
};
setTimeout(onChange);
window.onresize = onChange;
const gui = new dat.GUI();
gui.add(light, 'distance', 0, 100).onChange(onChange);
gui.add(light, 'decay', 0, 4).onChange(onChange);
gui.add(light, 'power', 0, 3000).onChange(onChange);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render() {
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
}
}
main();
html, body {
margin: 0;
height: 100%;
}
#c {
width: 100%;
height: 100%;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.2/dat.gui.min.js"></script>
<canvas id="c"></canvas>
【问题讨论】:
-
不是答案:距离单位通常以米为单位。有关
distance在您的情况下如何影响照明的说明,请参阅bsdfs.glsl中的内联 cmets。 -
阅读linked paper page 32 这显然是一种黑客行为。
distance设置主要在那里,因此 3D 引擎可以知道光线何时超出范围并且不必被视为贡献,因此可以忽略。不过,它并没有真正提供任何关于如何设置它的指导。我听起来基本上是“由艺术家决定”,尽管我想你可以计算出无限距离的光何时低于某个阈值并将距离设置为该阈值或略高。 -
也就是说,如果我正确理解了three.js,three.js 不会进行任何灯光管理。场景中的所有灯光都会影响具有受该类型灯光影响的材质的所有对象。因此,
distance始终可以设置为 Infinity 或某个较大的数字,因为将其设置得更小没有意义,因为它不会被剔除? -
将
distance设置为零与基本灯光的无穷大相同。对于物理上正确的灯光,您必须阅读源代码以了解其后果。
标签: three.js