首页 > 解决方案 > 立体几何背后的光

问题描述

我正在创建一个集成 ThreeJs 的 HTML 文件,基本上我创建了 4 个球体,其中 1 个投射光,其他 3 个球体在墙上转动。当球体在墙后面时,它们不应该反射光线,我应该怎么做才能解决这个问题?

我已经尝试将围绕墙壁转动的球体的材质更改为 Lambert 和 Phong,将 castShadow 设置为 true,并将 recieveShadow 设置为 False

(function onLoad() {
  var camera, scene, renderer, orbitControls;
  
  init();
  animate();

  function init() {
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.set(0, 30, -100);

    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xffffff);
    scene.add(camera);
    
    orbitControls = new THREE.OrbitControls(camera);
    
    escena = scene;

    esferaLuz = new THREE.SphereBufferGeometry(0.5, 16, 16);
    luzUno = new THREE.SpotLight(0xFFFFFF, 1);
    luzUno.angle = Math.PI / 12;
    luzUno.penumbra = 0.05;
    luzUno.decay = 2;
    luzUno.position.set(-30, 40, -5);
    mtLuzUno = new THREE.MeshBasicMaterial({color: 0xFFFFFF});
    mallaLuzUno = new THREE.Mesh(esferaLuz, mtLuzUno);
    luzUno.add(mallaLuzUno);
    escena.add(luzUno);    

    luzUno.castShadow = true;
    luzUno.shadow.mapSize.width = 1024;
    luzUno.shadow.mapSize.height = 1024;
    luzUno.shadow.camera.near = 10;
    luzUno.shadow.camera.far = 200;

    luzMap = new THREE.SpotLightHelper(luzUno);
    escena.add(luzMap);

    sombraMap = new THREE.CameraHelper(luzUno.shadow.camera);
    escena.add(sombraMap);

    var luzAmbiente = new THREE.AmbientLight( 0xffffff, 0.1 );
    escena.add(luzAmbiente);


    geometriaPlana = new THREE.CubeGeometry(100, 100, 2, 2);
    mtPlano = new THREE.MeshLambertMaterial({color: 0x000000});
    mtPlano.transparent = false;
    mtPlano.depthWrite = true;
    mallaPlano = new THREE.Mesh(geometriaPlana, mtPlano);
    mallaPlano.rotation.x = -0.5*Math.PI;
    mallaPlano.position.x = 15;
    mallaPlano.position.y = 0;
    mallaPlano.position.z = 0;
    mallaPlano.receiveShadow = true;
    escena.add(mallaPlano);

    objEsfera = new THREE.SphereGeometry(5, 100, 100);
    mtObjEsfera = new THREE.MeshPhongMaterial({color: 0xFFFFFF, specular:0xFFFFFF, shininess: 1024});
    mallaObjEsfera3 = new THREE.Mesh(objEsfera, mtObjEsfera);
    mallaObjEsfera3.position.set(20, 0, 0);
    mallaObjEsfera3.castShadow = true;
    mallaObjEsfera3.receiveShadow = false;
    escena.add(mallaObjEsfera3);

    objEsfera = new THREE.SphereGeometry(5, 100, 100);
    mtObjEsfera = new THREE.MeshPhongMaterial({color: 0xF90E0E, specular:0xF90E0E, shininess: 512});
    mallaObjEsfera2 = new THREE.Mesh(objEsfera, mtObjEsfera);
    mallaObjEsfera2.position.set(5, 0, 0);
    mallaObjEsfera2.castShadow = true;
    mallaObjEsfera2.receiveShadow = false;
    escena.add(mallaObjEsfera2);

    objEsfera = new THREE.SphereGeometry(5, 100, 100);
    mtObjEsfera = new THREE.MeshLambertMaterial({color: 0xF2E406});
    mallaObjEsfera = new THREE.Mesh(objEsfera, mtObjEsfera);
    mallaObjEsfera.position.set(-10, 0, 0);
    mallaObjEsfera.castShadow = true;
    mallaObjEsfera.receiveShadow = false;
    escena.add(mallaObjEsfera);

    renderer = new THREE.WebGLRenderer({antialias: true});
    renderer.setPixelRatio( window.devicePixelRatio);
    renderer.setClearColor(0xEEEEEE);
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.renderReverseSided = false;
    renderer.sortObjects = false
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.setSize( window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    renderer.gammaInput = true;
    renderer.gammaOutput = true;

    window.onresize = function() {
        renderer.setSize(window.innerWidth, window.innerHeight);
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
    }
}

  function animate() {
    requestAnimationFrame(animate);
    orbitControls.update();
    render();
  }

  function render() {
    renderer.render(scene, camera);
  }
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

我希望当球体在墙后面时,不要显示任何类型的光反射,但是当球体在前面时会反射光。

标签: javascriptthree.js

解决方案


实现预期结果的一种方法是使用阴影。所以你必须为你的球体和你的地面设置和Object3D.castShadow设置,就像下面的例子一样:Object3D.receiveShadowtrue

https://jsfiddle.net/85q3sfeg/

另请记住,three.js目前不支持选择性照明。这个问题已经在 github 上讨论过:https ://github.com/mrdoob/three.js/issues/5180

假设场景中的所有对象都应用了光照材质,您无法定义哪些光源应该影响哪些对象。

three.js R103


推荐阅读