重叠的半透明对象未按预期呈现

时间:2018-11-27 13:25:33

标签: three.js

我有两个重叠的半透明盒,我希望看到它们都与视角无关。第一张图片从侧面显示了一个渲染,并且在大盒子中可以看到小盒子。第二个图像显示相同的场景,但形成另一个视角。如您所见,较小的框是可见的,但是带有较大框的部分是不可见的。我想念什么?

small box visible within big box small box not visible within big box

var camera, scene, renderer;
init();
animate();

function init() {
  // Renderer.
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  
  // Add renderer to page
  document.body.appendChild(renderer.domElement);

  // Create camera.
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 50);
  camera.position.set(2, 2, 2);
  camera.lookAt(new THREE.Vector3(0.0, 0.0, 0.0));

  // Create scene.
  scene = new THREE.Scene();

  // Create material
  var material = new THREE.MeshStandardMaterial();
  material.transparent = true;
  material.opacity = 0.5;

  // Create cube and add to scene.
  var geometry1 = new THREE.BoxGeometry(1, 1, 1);
  var mesh1 = new THREE.Mesh(geometry1, material);
  mesh1.position.set(0, 0, 0);
  //mesh1.castShadow = true;
  scene.add(mesh1);

// Create cube and add to scene.
  var geometry2 = new THREE.BoxGeometry(0.5, 0.5, 0.5);
  var mesh2 = new THREE.Mesh(geometry2, material);
  mesh2.position.set(0.0, 0, 0.5);
  //mesh2.castShadow = true;
  scene.add(mesh2);

  var spotLight = new THREE.SpotLight(0xffffff, 0.32);
  spotLight.position.set(0, 5, 0);
  spotLight.castShadow = true;
  spotLight.shadow.mapSize.width = 2048;
  spotLight.shadow.mapSize.height = 2048;
  spotLight.shadow.camera.near = 0.1;
  spotLight.shadow.camera.far = 20;  
  scene.add(spotLight);

	let hemiLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.8);
	scene.add(hemiLight);
  
  // Ground plane
  var groundGeo = new THREE.PlaneBufferGeometry(50, 50);
  var groundMat = new THREE.MeshStandardMaterial({color: 0xffffff});
  var ground = new THREE.Mesh(groundGeo, groundMat);
  ground.rotation.x = -Math.PI / 2;
  ground.position.y = -0.5;
  ground.receiveShadow = true;
  scene.add(ground);

  // Add listener for window resize.
  window.addEventListener('resize', onWindowResize, false);

    let controls = new THREE.OrbitControls(camera);
    controls.enableZoom = true;
    controls.enablePan = false;
    controls.maxDistance = 20.0;
    controls.minPolarAngle = 0;
    controls.maxPolarAngle = Math.PI / 2;
    controls.target.set(0, 0, 0);
    controls.update();

}

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
  padding: 0;
  margin: 0;
}

canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

1 个答案:

答案 0 :(得分:1)

WebGL中的透明对象有时会出现问题。全部与渲染顺序有关:如果小立方体在大立方体之后进行渲染,渲染应如何表现? This question提供了一些您可能会觉得有用的信息。

在您的特定情况下(尽管不一定总是如此),一种解决方案可能是禁用渲染器对象排序:

renderer.sortObjects = false;

(!)确保以正确的顺序添加对象,即,先是小立方体,然后是大立方体。这是您的代码段的更新版本:

var camera, scene, renderer;
init();
animate();

function init() {
  // Renderer.
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  renderer.sortObjects = false;
  
  // Add renderer to page
  document.body.appendChild(renderer.domElement);

  // Create camera.
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 50);
  camera.position.set(2, 2, 2);
  camera.lookAt(new THREE.Vector3(0.0, 0.0, 0.0));

  // Create scene.
  scene = new THREE.Scene();

  // Create material
  var material = new THREE.MeshStandardMaterial();
  material.transparent = true;
  material.opacity = 0.5;
  
  // Create cube and add to scene.
  var geometry2 = new THREE.BoxGeometry(0.5, 0.5, 0.5);
  var mesh2 = new THREE.Mesh(geometry2, material);
  mesh2.position.set(0.0, 0, 0.5);
  //mesh2.castShadow = true;
  scene.add(mesh2);

  // Create cube and add to scene.
  var geometry1 = new THREE.BoxGeometry(1, 1, 1);
  var mesh1 = new THREE.Mesh(geometry1, material);
  mesh1.position.set(0, 0, 0);
  //mesh1.castShadow = true;
  scene.add(mesh1);

  var spotLight = new THREE.SpotLight(0xffffff, 0.32);
  spotLight.position.set(0, 5, 0);
  spotLight.castShadow = true;
  spotLight.shadow.mapSize.width = 2048;
  spotLight.shadow.mapSize.height = 2048;
  spotLight.shadow.camera.near = 0.1;
  spotLight.shadow.camera.far = 20;  
  scene.add(spotLight);

	let hemiLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.8);
	scene.add(hemiLight);
  
  // Ground plane
  var groundGeo = new THREE.PlaneBufferGeometry(50, 50);
  var groundMat = new THREE.MeshStandardMaterial({color: 0xffffff});
  var ground = new THREE.Mesh(groundGeo, groundMat);
  ground.rotation.x = -Math.PI / 2;
  ground.position.y = -0.5;
  ground.receiveShadow = true;
  scene.add(ground);

  // Add listener for window resize.
  window.addEventListener('resize', onWindowResize, false);

    let controls = new THREE.OrbitControls(camera);
    controls.enableZoom = true;
    controls.enablePan = false;
    controls.maxDistance = 20.0;
    controls.minPolarAngle = 0;
    controls.maxPolarAngle = Math.PI / 2;
    controls.target.set(0, 0, 0);
    controls.update();

}

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
  padding: 0;
  margin: 0;
}

canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>