5

2 つのコラーダ オブジェクトとディレクショナル ライトを含むシーンがあります。最初の collada はほぼ平面で、2 番目の collada は複数のボックスで構成されています。

シーンがレンダリングされると、地面に投じられた影はかなりうまくレンダリングされますが、いくつかの「側面」の影が実際に取り除かれているように見えます。

これが影のスクリーンショットです.

答えを探していたときに、collada に問題がある可能性があることがわかったので、シーンに基本的な立方体を追加しました (何よりも大きい立方体) が、同じ問題があるようです。

誰かがヒントを持っているか、この問題をすでに知っていますか?

Google Chrome と Mozilla Firefox (MacOS) でテストされた、最新の three.js リビジョン atm (r71) を使用しています。shadowCascade (私は使用しません) に関連するものを除いて、ディレクショナル ライトのほぼすべての shadow* 属性を微調整しようとしました。また、シャドウ関連のレンダラーの属性を微調整するテストも行いました。

これが私のライトのセットアップです:

var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.target.position = THREE.Vector3(0, 0, 0);
directionalLight.position.set( 250, 500, 250 );
directionalLight.castShadow = true;
directionalLight.shadowCameraNear = 100;
directionalLight.shadowCameraFar = 1000;
directionalLight.shadowMapWidth = 2048;
directionalLight.shadowMapHeight = 2048;
directionalLight.shadowBias = 0.0001;
directionalLight.shadowDarkness = 0.5;
directionalLight.shadowCameraLeft = -300;
directionalLight.shadowCameraRight = 300;
directionalLight.shadowCameraTop = 300;
directionalLight.shadowCameraBottom = -300;
directionalLight.shadowCameraVisible = true;

私の collada オブジェクトはちょっと大きいので、shadowCamera の境界も同じです。

私のレンダラーのセットアップ:

renderer = new THREE.WebGLRenderer( {antialias: true} );
renderer.setClearColor(0x222222);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );

これはシーンの別のビューです シーンの別のビューは次のとおりです(主に私のライト設定を示しています)。

編集:ここにスニペットがあります:

var container;
var camera, scene, renderer, controls;
var particleLight;

scene = new THREE.Scene();
init();
animate();

function init() {

  container = document.createElement( 'div' );
  document.body.appendChild( container );
  camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
  camera.position.set( 300, 100, 0 );

// Controls
  controls = new THREE.OrbitControls( camera );

  
  
// Cube
  var geometry = new THREE.BoxGeometry( 100, 100, 100 );
  var material = new THREE.MeshLambertMaterial();
  var cube = new THREE.Mesh( geometry, material );
  cube.position.y = 50;
  cube.rotation.y = 0.8;
  cube.castShadow = true;
  cube.receiveShadow = true;
  scene.add( cube );

// Plane
  var planeGeometry = new THREE.PlaneBufferGeometry( 300, 300, 300 );
  var plane = new THREE.Mesh( planeGeometry, material );
  plane.position.set( 0, 0, 0 );
  plane.rotation.x = -1.6;
  plane.castShadow = true;
  plane.receiveShadow = true;
  scene.add( plane );
  
// Light

  var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
  directionalLight.target.position = THREE.Vector3(0, 0, 0);
  directionalLight.position.set( 250, 500, 250 );
  directionalLight.castShadow = true;
  directionalLight.shadowCameraNear = 100;
  directionalLight.shadowCameraFar = 1000;
  directionalLight.shadowMapWidth = 2048;
  directionalLight.shadowMapHeight = 2048;
  directionalLight.shadowBias = 0.0001;
  directionalLight.shadowDarkness = 0.5;
  directionalLight.shadowCameraLeft = -300;
  directionalLight.shadowCameraRight = 300;
  directionalLight.shadowCameraTop = 300;
  directionalLight.shadowCameraBottom = -300;
  directionalLight.shadowCameraVisible = true;
  scene.add( directionalLight );

  scene.add( new THREE.AmbientLight( 0x555555 ) );
  renderer = new THREE.WebGLRenderer( {antialias: true} );
  renderer.setClearColor(0x222222);
  renderer.shadowMapEnabled = true;
  renderer.shadowMapSoft = true;
  renderer.shadowMapType = THREE.PCFSoftShadowMap;
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  container.appendChild( renderer.domElement );

  window.addEventListener( 'resize', onWindowResize, false );
}

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


function animate() {
  requestAnimationFrame( animate );
  render();
}

var clock = new THREE.Clock();

function render() {
  var timer = Date.now() * 0.0005;
  camera.lookAt(new THREE.Vector3(0, 0, 0));
  renderer.render( scene, camera );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>

前もって感謝します。

4

1 に答える 1

2

ディレクショナル ライトの光線がジオメトリの一部の面と正確に平行であるため、セルフ シャドウイングが発生しています。ディレクショナル ライトを少し別の場所に移動します。例えば、

directionalLight.position.set( 250, 500, 200 );

通常、light.shadow.biasセルフ シャドウイングの問題を解決するために使用されますが、あなたの場合のように、光線と顔が平行な場合は効果的ではありません。

また、shadow.bias負の値に設定して、他の面のアーティファクトを軽減します。

directionalLight.shadow.bias = - 0.01;

残念ながら、これは通常どおり、別のアーティファクト「ピーターパンニング」になります。

この種のトレードオフは一般的です。許容できる妥協点を見つける必要があります。(カメラの位置に基づいてバイアスを設定するかもしれません。)

three.js r.75

于 2015-06-12T12:28:33.590 に答える