I'm trying to add a spotlight effect on different parts of my scene but for some reason I'm unable to accomplish it. I tried using PointLight and SpotLight but they both didn't work.
Example of the code
var pointLight = new THREE.PointLight( 0xffffff, 1, 10 );
pointLight.position.set(obj.position);
scene.add( pointLight );
The light effect doesn't need to follow the mouse movement. It just needs to appear after specific event trigger.
I'm not sure if the spotLight or the pointLight is the right way to do this.
I appreciate any feedback on what approach I should take and what is the best way to accomplish this animation.
Attempted adding SpotLight like so
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 0, 0, 0 );
spotLight.shadow.mapSize.width = 512;
spotLight.shadow.mapSize.height = 512;
spotLight.target = obj;
spotLight.intensity = 2;
scene.add( spotLight );
var spotLightHelper = new THREE.SpotLightHelper( spotLight );
scene.add( spotLightHelper );
Related
If you take a look here which is done with r71 the shadows work:
var shadowlight = new THREE.DirectionalLight( 0xffffff, 1.8 );
shadowlight.position.set( 0, 100, 0 );
shadowlight.castShadow = true;
shadowlight.shadowDarkness = 0.1;
this.scene.add(shadowlight);
this.renderer.setClearColor( 0xf1c140, 1 );
this.renderer.shadowMapEnabled = true;
this.renderer.shadowMapType = THREE.PCFSoftShadowMap;
https://codepen.io/nicolasdnl/pen/VYRXWr
However, if I change the version to 104, and make the necessary changes that it suggests:
.shadowMapEnabled is now .shadowMap.enabled.
.shadowMapType is now .shadowMap.type.
THREE.Light: .shadowDarkness has been removed.
The shadow doesn't work any more: https://codepen.io/bertug48/pen/YMowKx
How to enable the shadows like r71 on v104?
MeshBasicMaterial is not able to receive shadows for over three years now. You have to use a lit material for your ground or add an additional ground mesh with an instance of THREE.ShadowMaterial.
Demo: https://jsfiddle.net/38weog40/
var planeGeometry = new THREE.PlaneGeometry( 200, 200 );
planeGeometry.rotateX( - Math.PI / 2 );
var planeMaterial = new THREE.ShadowMaterial();
planeMaterial.opacity = 0.2;
var plane = new THREE.Mesh( planeGeometry, planeMaterial );
plane.position.y = -200;
plane.receiveShadow = true;
scene.add( plane );
BTW: Here is the reason why MeshBasicMaterial does not receive shadows anymore: https://github.com/mrdoob/three.js/issues/8116#issuecomment-183540170
three.js R104
I'm struggling in my attempt to light an object, make it tween towards camera and have the light follow the tween.
Basically I want to darken the background and tween a 3D object towards the camera, and set a directional light pointing at it so it has nice, smooth, uniform lighting.
Directional lights i add to the object don't show up, latest I've tried is:
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.position.set( 0, 0, -100);
directionalLight.lookAt(object);
directionalLight.shadowCameraVisible = true;
object.add( directionalLight );
I've also tried PointLights near the camera, these kind of work but it's a very sharp light, not smooth and doesn't seem to light all the objects the same.
Using something like this
hslight1 = new THREE.PointLight( 0xffffff,0.9,100 );
hslight1.position.set(0,10,0);
scene.add( hslight1 );
hslight2 = new THREE.PointLight( 0xffffff,0.9,100 );
hslight2.position.set(0,0,0);
scene.add( hslight2 );
Anyone get any ideas on any way to uniformly light an object3D that is tweening towards the camera using
var dist = (size/screen) * (object.scale.x * 2);
var pLocal = new THREE.Vector3( 0, 0, -dist );
var target = pLocal.applyMatrix4( camera.matrixWorld );
var tweenMove = new TWEEN.Tween(object.position).to(target, 1500).easing(TWEEN.Easing.Cubic.InOut);
tweenMove.onUpdate(function(){object.lookAt(camera.position);});
Fixed this by adding the light to the camera
camera.add( light );
I have an issue with shadow map showing on the back side of an object, I have been fighting with that for almost two days now, thinking I was surely doing something wrong.
Then I wrote this jsFiddle : http://jsfiddle.net/gui2one/ec1snfee/
code below :
// shadow map issue
var light ,mesh, renderer, scene, camera, controls;
var clock = new THREE.Clock({autoStart:true});
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.shadowMapEnabled = true;
renderer.setSize( window.innerWidth, window.innerHeight );
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( -58, 10, 29 );
// controls
controls = new THREE.OrbitControls( camera );
// ambient
scene.add( new THREE.AmbientLight( 0x222222 ) );
// light
light = new THREE.SpotLight();
light.position.set( 20, 0, 0 );
//light.target.position.set(1000,0,0);
light.castShadow = true;
light.shadowBias = -0.001;
light.shadowCameraNear = 1;
light.shadowCameraFar = 100;
light.shadowMapWidth = 2048;
light.shadowMapHeight = 2048;
light.shadowCameraVisible = true;
scene.add( light );
// axes
scene.add( new THREE.AxisHelper( 5 ) );
var materialTest = new THREE.MeshPhongMaterial();
var planetTestGeo = new THREE.SphereGeometry(5);
var planetTest = new THREE.Mesh(planetTestGeo, materialTest);
planetTest.castShadow = true;
planetTest.receiveShadow = true;
scene.add(planetTest);
planetTest.position.set(-30,0,0);
var moonTestGeo = new THREE.SphereGeometry(1);
var moonTest = new THREE.Mesh(moonTestGeo, materialTest);
moonTest.castShadow = true;
moonTest.receiveShadow = true;
scene.add(moonTest);
moonTest.position.set(planetTest.position.x+10 ,planetTest.position.y-0.5 ,planetTest.position.z);
camera.lookAt(moonTest.position);
}
function animate() {
requestAnimationFrame( animate );
//controls.update();
renderer.render( scene, camera );
}
and then I noticed this question ( more than 2 years ago )
THREE.JS Shadow on opposite side of light.
Is there a work around that now ?
I am trying to make an animated solar system. And I can't use different objects , or different materials to solve this problem, because planets and moons evidently always rotate on themselves and around each other.
Easy fix:
light.shadowBias = 0.001;
instead of
light.shadowBias = -0.001;
I've seen examples on the web using negative bias. I'm not sure if that is correct behaviour.
Good luck!
UPDATE
You will see some shadow acne on the light terminal on the sphere. This appears to be an issue with three.js shadow mapping methods and is due for an update AFAIK.
I have a very simple example: a spot light pointed at a plane. I am expecting to see a cone of light whose diameter depends on the setting of the spot light angle. I cannot see any cone, the whole plane is illuminated, even for very narrow settings of angle.
Here is my jfiddle: http://jsfiddle.net/blwoodley/WLtL4/1/
I'd love to know the source code that produced this picture from https://github.com/mrdoob/three.js/pull/3291 by West Langley. It obviously is working fine in that case.
So I must be doing something obviously wrong, but I can't figure it out.
Some of the code from the jfiddle, it doesn't get much simpler than this:
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.x = 100;
camera.position.y = 100;
camera.position.z = 200;
camera.lookAt({x: 0,y: 0,z: 0});
scene = new THREE.Scene();
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floorMaterial = new THREE.MeshLambertMaterial({ color: 0x222222, side:THREE.DoubleSide });
floor = new THREE.Mesh(new THREE.PlaneGeometry(2000,2000,10,10), floorMaterial);
floor.rotation.x = Math.PI / 2;
floor.position.y = -40;
scene.add(floor);
var light;
light = new THREE.SpotLight(0x008888);
light.position.set(0, 40, 0);
light.lookAt(floor);
light.angle = Math.PI/4;
light.intensity = 30;
light.distance=0;
scene.add(light);
// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
container.appendChild(webglRenderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
This is subtle.
You are using MeshLambertMaterial for the plane. You need to change it to MeshPhongMaterial, so the lighting is rendered properly.
As explained here, for MeshLambertMaterial, the illumination calculation is performed only at each vertex.
For MeshPhongMaterial, the illumination calculation is performed at each texel.
So make these changes
floorGeometry = new THREE.PlaneGeometry( 1000, 1000 ); // no need to tessellate it now
var floorMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff } ); // 0x222222 is too dark
light.intensity = 1; // a reasonable value
Updated fiddle: http://jsfiddle.net/WLtL4/5/
three.js r.63
Also try to disable target for testing.
I'm getting really weird behavior from it. Sometimes it makes it not render the light at all, no idea why yet. I'll make a demo of the problem later.
I've been trying for bigger parts of the night to make a export code that quickly will let me texture cubes and export them to a game i'm making, but for some reason I can't make my cube to cover the entire 128x128 width and height that I want it to have.
I have the following code:
function init(){
if( Detector.webgl ){
renderer = new THREE.WebGLRenderer({
antialias : false, // to get smoother output
preserveDrawingBuffer : true // to allow screenshot
});
renderer.setClearColorHex( 0xBBBBBB, 1 );
// uncomment if webgl is required
//}else{
// Detector.addGetWebGLMessage();
// return true;
}else{
renderer = new THREE.CanvasRenderer();
}
renderer.setSize(128,128);
document.getElementById('container').appendChild(renderer.domElement);
// add Stats.js - https://github.com/mrdoob/stats.js
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
document.body.appendChild( stats.domElement );
var zoom = 1.0;
// create a scene
scene = new THREE.Scene();
// put a camera in the scene
camera = new THREE.OrthographicCamera(WIDTH / -zoom, HEIGHT / zoom, WIDTH / zoom, HEIGHT / -zoom, -2000, 1000);
//camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(0.45,0.45,0.45);
camera.lookAt(scene.position);
//camera.position.set(0, 0, 5);
scene.add(camera);
// create a camera contol
//cameraControls = new THREEx.DragPanControls(camera)
// transparently support window resize
THREEx.WindowResize.bind(renderer, camera);
// allow 'p' to make screenshot
THREEx.Screenshot.bindKey(renderer);
// allow 'f' to go fullscreen where this feature is supported
//if( THREEx.FullScreen.available() ){
// THREEx.FullScreen.bindKey();
// document.getElementById('inlineDoc').innerHTML += "- <i>f</i> for fullscreen";
//}
// here you add your objects
// - you will most likely replace this part by your own
//var geometry = new THREE.TorusGeometry( 1, 0.42 );
var cubeSize = 128;
var geometry = new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize );
var material = new THREE.MeshNormalMaterial();
mesh= new THREE.Mesh( geometry, material );
mesh.rotation.x = 0;
mesh.rotation.y = 0;
mesh.rotation.z = 0;
scene.add( mesh );
}
I've been trying out different "zooms" but it still ends up either too big or too small.
The point with all this is to end up with a code that can generate something like this:
https://dl.dropboxusercontent.com/u/5256694/cube_ex.png
What am I doing wrong?
Kind Regards
Hiam
Instead of thinking about the parameters of THREE.OrthographicCamera as "zoom" levels, you should think of them as coordinates of boundary planes for what the camera is able to see.
Also see the answer to Three.js - Orthographic camera for more details about using orthographic cameras in Three.js