我正在使用three.js制作地下城爬行类游戏。我使用MeshBasicMaterial将所有内容设为“ truebright”,以使整个副本始终可见。但是,我想添加穿过门口或墙壁上的缝隙的“奖励”灯,以营造氛围。但是,BasicMaterial上没有显示光,所以我切换到Phong来测试地板上的光。现在我的地板是黑色的!最有可能是因为没有全局视野。
有什么方法可以在允许使用不同颜色的灯光的同时模拟MeshBasicMaterial的属性?地牢的所有四个侧面都是封闭的,因此我想放一个巨大的全局光会在各处投射阴影或覆盖地面上的颜色。
不是我的问题的主要焦点,而是另外:我如何做到这一点,以使光线被墙壁挡住,而不是仅仅穿过墙壁?墙壁只是由地图系统生成的1x1x1 3d网格立方体。
最佳答案
切换到MeshPhongMaterial
后,材质将变为阴影。您可以设置一些参数使其更接近MeshBasicMaterial
,但是您仍将获得渐变照明,无论如何,这实际上是您在寻找“额外”照明的目的。在下面的代码中,我将shininess
属性设置为0,这消除了Phong阴影的强光效果。
为了使光线不流过墙壁,您需要实施阴影投射。在THREE.js中,这实际上确实很简单,并且在线上有大量描述如何执行此操作的文章,因此在此我将不重复任何内容。但是,正如您在我的简单示例中看到的那样,您需要将网格设置为投射和接收阴影(分别为castShadows
/ receiveShadows
),并设置灯光以同时投射阴影(castShadows
)。
var renderer, scene, camera, controls, stats;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 70,
NEAR = 1,
FAR = 1000;
function populateScene() {
var cfgeo = new THREE.PlaneBufferGeometry(100, 100),
lwallgeo = new THREE.PlaneBufferGeometry(20, 20),
rwallgeo = new THREE.PlaneBufferGeometry(50, 20),
farwallgeo = new THREE.PlaneBufferGeometry(50, 20),
bumpgeo = new THREE.PlaneBufferGeometry(10, 10);
var mat = new THREE.MeshPhongMaterial({
color: 0xcccccc,
emissive: new THREE.Color(0x0c0c0c),
shininess: 0,
side: THREE.DoubleSide
});
var ceiling = new THREE.Mesh(cfgeo, mat),
floor = new THREE.Mesh(cfgeo, mat),
lwall = new THREE.Mesh(lwallgeo, mat),
rwall = new THREE.Mesh(rwallgeo, mat),
farwall = new THREE.Mesh(farwallgeo, mat),
bump1 = new THREE.Mesh(bumpgeo, mat),
bump2 = new THREE.Mesh(bumpgeo, mat);
ceiling.castShadow = true;
ceiling.receiveShadow = true;
floor.castShadow = true;
floor.receiveShadow = true;
lwall.castShadow = true;
lwall.receiveShadow = true;
rwall.castShadow = true;
rwall.receiveShadow = true;
farwall.castShadow = true;
farwall.receiveShadow = true;
bump1.castShadow = true;
bump1.receiveShadow = true;
bump2.castShadow = true;
bump2.receiveShadow = true;
ceiling.position.y = 10;
ceiling.rotation.x = Math.PI / 2;
floor.position.y = -10;
floor.rotation.x = Math.PI / -2;
lwall.rotation.y = Math.PI / 2;
lwall.position.x = -10;
rwall.rotation.y = Math.PI / -2;
rwall.position.x = 10;
rwall.position.y = 2;
farwall.position.z = -20;
bump1.rotation.y = Math.PI / -2;
bump2.rotation.y = Math.PI / -2;
bump1.position.set(10, -10, -15);
bump2.position.set(10, -10, 5);
scene.add(ceiling);
scene.add(floor);
scene.add(lwall);
scene.add(rwall);
scene.add(farwall);
scene.add(bump1);
scene.add(bump2);
var bonus = new THREE.SpotLight(0xcccc00, 0.5);
bonus.position.set(15, -7, -5);
bonus.castShadow = true;
bonus.distance = 20;
var tgt = new THREE.Object3D();
tgt.position.set(0, -10, -10);
bonus.target = tgt;
scene.add(bonus);
scene.add(tgt);
}
function init() {
document.body.style.backgroundColor = "slateGray";
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 15;
scene.add(camera);
controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.dynamicDampingFactor = 0.5;
controls.rotateSpeed = 3;
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
resize();
window.onresize = resize;
populateScene();
animate();
}
function resize() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}
function render() {
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
stats.update();
}
function threeReady() {
init();
}
(function() {
function addScript(url, callback) {
callback = callback || function() {};
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("https://threejs.org/build/three.js", function() {
addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function() {
addScript("https://threejs.org/examples/js/libs/stats.min.js", function() {
threeReady();
})
})
})
})();
关于javascript - THREE.js:在允许有色灯光的同时模拟MeshBasicMaterial,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44480512/