Есть ли способ предотвратить попадание света на лица внутри тени?
Я работаю над городской сценой в Three.js и пока что экспериментирую с освещением и тенью только в одном здании. Здание было смоделировано в 3DS Max, затем экспортировано в OBJ, а затем преобразовано с помощью преобразователя Python из командной строки.
Вы заметите, что модель здания представляет собой отдельный объект, и я использую самозатенение. Однако нижняя часть здания, которая находится в тени, все еще освещается желто-белым направленным светом. Я предполагаю, что это потому, что его освещенность просто рассчитывается по тому, насколько он обращен к источнику света, без учета всего, что может быть между ним и источником света.
Я искал метод, чтобы "исправить" это и сделать его более реалистичным, чтобы меш мешал свету попадать в него позади, даже внутри себя. Мне нужно попасть в шейдеры или карты нормалей? Или что-то еще целиком?
Кроме того, этот вопрос может быть дубликатом, но код или примеры не были приведены, поэтому я не уверен: свет проникает сквозь сетки. Извините заранее, если это проблема.
JSFiddle находится здесь: http://jsfiddle.net/mrfolkblues/u01jwg53/
Соответствующая часть кода:
var T = THREE,
stats,
container,
camera = new T.PerspectiveCamera(40, window.innerWidth/window.innerHeight, 0.1, 200),
scene = new T.Scene(),
renderer = new T.WebGLRenderer({
antialias: true
}),
radius = 35, theta = 0, thetaDelta = 0, camtarget,
boundingbox, cube, plane, poly, polyMesh, sphere, line,
clock = new T.Clock();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
// construct
(function(){
container = document.createElement( 'div' );
document.body.appendChild( container );
// set up renderer
renderer.setClearColor( 0xf0f0f0 );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild(renderer.domElement);
var light = new T.DirectionalLight( 0xfff3cb, 1.25 );
light.position.set( 60, 25, 40 );
var light2 = new T.DirectionalLight( 0x204fae, 1.25 );
light2.position.set( -30, 40, 0 );
light.castShadow = true;
light.shadowDarkness = 0.33;
light.shadowCameraTop = 20;
light.shadowCameraRight = 20;
light.shadowCameraBottom = -20;
light.shadowCameraLeft = -20;
light.shadowCameraNear = 0;
light.shadowCameraFar = 200;
light.shadowMapWidth = 2048;
light.shadowMapHeight = 2048;
light.shadowBias = 0.0002;
scene.add( light );
scene.add( light2 );
var cube = createCube([0.5, 0.5, 0.5], [1.5, 10, 0]);
// position camera
camera.position.x = 0;
camera.position.y = 20; // move camera position up
camera.position.z = radius; // move camera out
camtarget = cube.position;
camera.lookAt( camtarget );
createPlane();
var loader = new T.JSONLoader();
var parsed = loader.parse(window.buildingModel);
var material = new T.MeshLambertMaterial( {
color: 0xffffff
} );
var object = new THREE.Mesh( parsed.geometry, material );
object.castShadow = true;
object.receiveShadow = true;
scene.add( object );
object.position.x = 30;
object.position.y = 0;
object.position.z = 15;
// add event listeners
window.addEventListener( 'resize', onWindowResize, false );
render();
animate();
})();
2 ответа
То, что вы хотите сделать, не решается с помощью three.js или любой другой подобной библиотеки, основанной на webgl. То, что вы хотите, решается Global Illumination
методы, которые выходят за рамки Three.js.
В three.js r.73 тени реализуются с использованием аппроксимации: области в тени просто затемняются с помощью установленного вами коэффициента:
light.shadowDarkness = 0.33;
Итак, если вы установите shadowDarkness
1, ваша проблема исчезнет. Конечно, это выглядит не так хорошо.
Обновленная скрипка: http://jsfiddle.net/u01jwg53/1/
Имейте в виду, что тени будут улучшены в будущих выпусках three.js.
Three.JS R.73