Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
177 views
in Technique[技术] by (71.8m points)

javascript - Stripped shadows on collada objects

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.

Here's a screenshot of the shadows.

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 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>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...