Stripped shadows on collada objects

一曲冷凌霜 提交于 2019-11-26 22:04:29

问题


I have a scene with two collada objects and a directional light. The first collada is pretty much a plane, and the second one is made of multiple boxes.

It appears that when the scene is rendered, some "side" shadows are really stripped, although the shadows casted on ground are pretty well rendered.

.

As I was searching for an answer, I figured out it might be a problem with my collada, so I added a basic cube to the scene (the big one above all), but it seems it has the same problem.

Does anyone have a tip or know this problem already?

I'm using the last three.js revision atm (r71), tested on Google Chrome and Mozilla Firefox (MacOS). I already tried to tweak pretty much all the shadow* attributes of the directional light, except the ones related with shadowCascade (which I don't use). I also tested to tweak shadow-related renderer's attributes.

Here's my light setup:

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;

My collada objects are kind of big, so are my shadowCamera bounds.

My renderer setup:

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 );

Here's another view of the scene

(mostly showing my light setup).

EDIT: Here's a snippet:

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>

Thanks in advance.


回答1:


You are getting self-shadowing because the rays of the directional light are exactly parallel to some of the faces of your geometry. Move the directional light to a slightly different location. For example,

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

Usually, light.shadow.bias is used to remedy self-shadowing problems, but it is not going to be effective when the light ray and face are parallel, as in your case.

Also, set shadow.bias to be negative to help alleviate artifacts on other faces.

directionalLight.shadow.bias = - 0.01;

This unfortunately will result, as it usually does, in another artifact: "Peter Panning".

These kinds of trade-offs are common. You are just going to have to find an acceptable compromise. (Maybe set the bias based on camera position.)

three.js r.75



来源:https://stackoverflow.com/questions/30799206/stripped-shadows-on-collada-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!