Three.js shadow not as expected - three.js

I'm trying to create a shadow under the cube in this jsfiddle, (code below) but the shadow turns out too big, and I don't think the right shape either. What's causing this shadow, and how can I fix it?
Thanks
var initScene, render,
projector, renderer, scene, ground, light,
camera, box, pointLight;
projector = new THREE.Projector;
scene = new THREE.Scene;
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColorHex(0x000000, 1);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
document.body.appendChild( renderer.domElement );
light = new THREE.DirectionalLight( 0xFFFFFF );
light.position.set( 20, 80, 0 );
light.target.position.copy( scene.position );
light.castShadow = true;
light.shadowCameraLeft = -60;
light.shadowCameraTop = -60;
light.shadowCameraRight = 60;
light.shadowCameraBottom = 60;
light.shadowCameraNear = 1;
light.shadowCameraFar = 2000;
light.shadowBias = 10;
light.shadowMapWidth = light.shadowMapHeight = 2040;
light.shadowDarkness = .7;
scene.add( light );
box = new THREE.Mesh(
new THREE.CubeGeometry( 5, 5, 40 ),
new THREE.MeshLambertMaterial({
color: 0xffffff,
opacity: 0.7,
transparent: true,
depthWrite: false
}));
box.position.set( 10, 10, 10 );
box.castShadow = true;
scene.add(box);
ground = new THREE.Mesh(
new THREE.CubeGeometry(1000, 1, 1000),
new THREE.MeshLambertMaterial({
color: 0xffffff,
opacity: 0.3,
transparent: true
}));
ground.receiveShadow = true;
scene.add( ground );
camera = new THREE.PerspectiveCamera(
35, window.innerWidth / window.innerHeight, 1, 1000
);
camera.position.set( 100, 100, 100 );
camera.lookAt( scene.position );
scene.add( camera );
renderer.render( scene, camera );
scene.simulate();

For some reason I cannot go to the fiddle but from what I see your cube is at (10,10,10) with size 5 and your light is at (20,80,0). My first guess is that your light is very close to the cube. Try moving the light to (200,200,0) and see what happens.

Related

Create a camera that can only stay in an orbit/dome above the ground

I have a camera
if (srims.state.staticData.cameraSettings.active) {
srims.camera = new THREE.PerspectiveCamera(
srims.state.staticData.cameraSettings.distance,
(window.innerWidth * 0.75) / window.innerHeight,
srims.state.staticData.cameraSettings.minDistance,
srims.state.staticData.cameraSettings.maxDistance
);
srims.camera.position.set(
srims.state.staticData.cameraSettings.position.x,
srims.state.staticData.cameraSettings.position.y,
srims.state.staticData.cameraSettings.position.z
);
srims.camera.up = new THREE.Vector3(0, 1, 0);
srims.camera.lookAt(new THREE.Vector3(0, 0, 0));
}
It works great, basically looks at 0, 0, 0 and i can orbit / zoom all the way around that target.
Let's say my scene has a floor placed on Y: 0 and we have a model on that floor and the model is 0, 0, 0.
Now the problem is, I don't want to see or go under the floor with my camera I want it to stay above Y.
Best example would be that the bounds of my camera are like a cut in half tennis ball placed on the floor. It's only above the floor, not a full ball translated half above and half below the floor.
Any examples or guidance would be great.
You can do this by setting OrbitControls.maxPolarAngle to Math.PI * 0.5.
var mesh, renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 20, 20, 20 );
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.maxPolarAngle = Math.PI * 0.5;
// ambient
scene.add( new THREE.AmbientLight( 0x222222 ) );
// light
var light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 20,20, 0 );
scene.add( light );
// axes
scene.add( new THREE.AxesHelper( 20 ) );
// geometry
var geometry = new THREE.SphereGeometry( 5, 12, 8 );
// material
var material = new THREE.MeshPhongMaterial( {
color: 0x00ffff,
flatShading: true,
transparent: true,
opacity: 0.7,
} );
// mesh
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
<script src="https://rawcdn.githack.com/mrdoob/three.js/r112/build/three.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r112/examples/js/controls/OrbitControls.js"></script>

Shadow on pure white

I'm trying to create a pure white scene where the only hint of depth is by moving a spotLight around with your mouse. I like the effect I have now but I was wondering how I could get the entire field (now gray) to be pure white, while keeping the shadow.
If I turn ambient light up I lose the shadow.
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 50, 0 );
var controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.minDistance = 20;
controls.maxDistance = 500;
controls.enablePan = false;
var ambient = new THREE.AmbientLight( 0xffffff, .7 );
scene.add( ambient );
spotLight = new THREE.SpotLight( 0xffffff, 1 );
spotLight.position.set( 0, 10, 0 );
spotLight.target.position.set( 0, 0, 0 );
spotLight.angle = 1.05;
spotLight.penumbra = 0.05;
spotLight.decay = 1;
spotLight.distance = 200;
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 10;
spotLight.shadow.camera.far = 200;
scene.add( spotLight );
lightHelper = new THREE.SpotLightHelper( spotLight );
// scene.add( lightHelper );
shadowCameraHelper = new THREE.CameraHelper( spotLight.shadow.camera );
// scene.add( shadowCameraHelper );
// scene.add( new THREE.AxisHelper( 10 ) );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, dithering: true } );
var geometry = new THREE.BoxGeometry( 2000, 1, 2000 );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0, - 1, 0 );
mesh.receiveShadow = true;
scene.add( mesh );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, dithering: true } );
geometry = new THREE.BoxGeometry( 3, 1, 2 );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0, 0, 0 );
mesh.castShadow = true;
scene.add( mesh );

three.js transparent sphere glitch

I have a transparent sphere and a spot light and that's about it. My sphere displays visual glitches, like striations.
see: http://jsfiddle.net/blwoodley/tvcogqkg/3/
(Note the grid is not necessary to manifest the bug. I just put it in there to show that transparency is working otherwise fine).
Any thoughts on how to get rid of these glitches? They seem to depend on the relative position of the camera and spot light.
Using three.js, r71.
Here is the code from the fiddle since SO seems to want it:
var SCREEN_WIDTH = window.innerWidth - 100;
var SCREEN_HEIGHT = window.innerHeight - 100;
var camera, scene, _planeMesh;
var canvasRenderer, webglRenderer;
var container, mesh, geometry, plane;
container = document.createElement('div');
document.body.appendChild(container);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.set( 380, 80, 100 );
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 180, 160, 0 );
var grid = new THREE.GridHelper(400, 40);
grid.position.y = -20;
scene.add(grid);
scene.add(spotLight);
camera.lookAt( scene.position );
var material = new THREE.MeshPhongMaterial( {
color: 0xaaaa00,
emissive: 0xaa0000,
specular: 0xaa00aa,
shininess: 10,
side: THREE.DoubleSide,
shading: THREE.SmoothShading,
opacity: .8, transparent: true } );
var size = 16.0;
var sphereGeo = new THREE.SphereGeometry( size, 32, 16 );
var mesh = new THREE.Mesh( sphereGeo, material);
scene.add(mesh);
var mesh = new THREE.Mesh( sphereGeo, material);
mesh.position.y = 40;
scene.add(mesh);
var mesh = new THREE.Mesh( sphereGeo, material);
mesh.position.x = 60;
scene.add(mesh);
// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
container.appendChild(webglRenderer.domElement);
animate();
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
webglRenderer.render(scene, camera);
}
Remove the attribute side: THREE.DoubleSide. Since you are drawing spheres, you don't need it.

Weird square on scene with SSAO shader

I'm running following code (jsfiddle: http://jsfiddle.net/sx9p7/ ) :
var scene, camera, renderer, composer;
var l1, l2, hemiLight;
var effectSSAO;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
renderer.shadowMapEnabled = true;
renderer.setClearColor( 0xd8e7ff );
renderer.setSize( 800,600);
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, 800 / 600, 1, 10000 );
camera.position.set(-200,100,-60);
camera.lookAt(new THREE.Vector3(0,0,0));
var container = document.createElement( 'div' );
document.body.appendChild( container );
composer = new THREE.EffectComposer( renderer );
composer.addPass( new THREE.RenderPass( scene, camera ) );
effectSSAO = new THREE.ShaderPass( THREE.SSAOShader );
effectSSAO.renderToScreen = true;
composer.addPass( effectSSAO );
hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.4 );
hemiLight.position.set( 0, 300, 0 );
scene.add( hemiLight );
l1 = new THREE.DirectionalLight( 0xffffff, 0.3);
l1.position.set( 100, 100, 0 );
l1.castShadow = true;
scene.add(l1);
l2 = new THREE.DirectionalLight( 0xffffff, 0.3);
l2.position.set( -100, 100, 0 );
l2.castShadow = true;
scene.add(l2);
var plane = new THREE.Mesh( new THREE.PlaneGeometry( 200, 200), new THREE.MeshLambertMaterial({ }) );
plane.receiveShadow = true;
plane.castShadow = true;
plane.rotation.x = - 90 * Math.PI / 180;
plane.position.set(0,0,0);
scene.add( plane );
var cube = new THREE.Mesh(new THREE.CubeGeometry(50, 50, 50), new THREE.MeshPhongMaterial( { color: 0xaaaaaa, ambient: 0xbbbbbb, specular: 0xcccccc, perPixel: true, vertexColors: THREE.FaceColors } ));
cube.receiveShadow = true;
cube.castShadow = true;
scene.add(cube);
}
function animate() {
requestAnimationFrame( animate );
composer.render();
}
and i have a problem with SSAO shader. I did try many parameters, codes, examples but still i can't remove that square which is in the middle of scene ( which sometime look like correct SSAO effect but in wrong position ??? )
If i will remove one directional light fragment is gone - but still no SSAO effect and shadows are still super very low resolution.
Well, 2 directional lights are strange anyway, just leave it at 1 for the moment.
Concerning the SSAO, see the shader and its numerous parameters. you would need to adjust those according to your scene. example:
effectSSAO .uniforms[ 'tDepth' ].value = depthTarget;
effectSSAO .uniforms[ 'size' ].value.set( width, height );
effectSSAO .uniforms[ 'cameraNear' ].value = 0.1;
effectSSAO .uniforms[ 'cameraFar' ].value = 1000;
As you see above, you also need more than just a few parameter tweaks.
The Three.SSAO shader expects a previously rendered depth pass to work properly.
See here for more help:
How to use the three.js SSAO shader?

THREE.js Texture is not visible with SVGRenderer

We've tried the next code:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.0001, 999);
camera.position.set( 0, 0, 3 );
scene.add( camera );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
var image = $('#tmp')[0]
var texture = new THREE.Texture(image);
texture.needsUpdate = true;
var img_material = new THREE.MeshBasicMaterial({color: 0x000000, map: texture });
var plane_geometry = new THREE.PlaneGeometry(2, 2);
var imageMesh = new THREE.Mesh(plane_geometry, img_material);
imageMesh.doubleSided = true;
scene.add(imageMesh);
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
$('#container').append( renderer.domElement );
renderer.render(scene, camera);
but when we switched to:
renderer = new THREE.SVGRenderer();
it stop rendering texture over image geometry. Can anybody say why so?
THREE.SVGRenderer doesn't support textures.

Resources