in my three js setting I have the following settings for a directional light:
private aLight: THREE.DirectionalLight;
this.aLight = new THREE.DirectionalLight(0xffffff, 1.0);
this.aLight.position.set(-5, 5, 5);
this.aScene.add(this.aLight);
In order to have the light following my camera and always illuminate my mesh I set the following in my render function:
private onRender() {
this.aLight.position.copy(this.aCamera.getWorldPosition());
window.requestAnimationFrame(_ => this.onRender());
this.aRenderer.render(this.aScene, this.aCamera);
Now, the object is always illuminated:
but if I zoom in the surfaces facing the camera are dark:
I would like to have my light always pointing from my camera to the object. What am I doing wrong?
If you want a light source to be coincident with your camera, the easiest solution is to use a point light and add it as a child of the camera. You can uses a pattern like this:
camera.position.set( 10, 10, 10 );
scene.add( camera ); // required in this case since the camera will have a child
// ambient
scene.add( new THREE.AmbientLight( 0xffffff, 0.1 ) ); // optional
// light
var light = new THREE.PointLight( 0xffffff, 1 );
camera.add( light );
If you are using a directional light, remember that a directional light has a target property, an Object3D. So if you zoom in, you will likely have to change target.position. Using a point light, as I explained above, is easier.
three.js r.86
Related
Im using OrbitControls and when i zoom in or move camera on some angles some of the meshes disappear.
This is my camera configuration right now :
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight,0.1, 3000 );
I tried to decrease the near plane but it doesnt work, i also add to the meshes materials that are disappearing THREE.DoubleSide and nothing seems to work. They are also animated via new way to animate fbx.
object.mixer = new THREE.AnimationMixer( object );
mixers.push( object.mixer );
var action = object.mixer.clipAction( object.animations[ 0 ] );
action.play();
dont know if that has anything relationship with the issue.
I'm having an issue when rendering a white material in ThreeJS version 87.
Here are the steps to replicate:
A white PNG image that is loaded as texture
This texture is used to create a MeshBasicMaterial (passed as parameter map)
The MeshBasicMaterial is used along a plane Geometry to create a Mesh
The Mesh is added to an empty Scene and rendered on a WebGLRenderer with alpha: true and clearColor as white
The problem is that the rendered texture now has grey edges on parts that should be fully white.
This happens with any image with white edges. I've also tried many different configurations for the renderer and the material but to no avail.
I've made a very simple CodePen that replicates the behavior as simple as possible. Does anyone know how can this problem be solved?
CodePen:
https://codepen.io/ivan-i1/pen/pZxwZX
var renderer, width, height, scene, camera, dataUrl, threeTexture, geometry, material, mesh;
width = window.innerWidth;
height = window.innerHeight;
dataUrl = '//data url from image';
threeTexture = new THREE.ImageUtils.loadTexture(dataUrl);
material = new THREE.MeshBasicMaterial({
map: threeTexture,
transparent: true,
alphaTest: 0.1
});
material.needsUpdate = true;
geometry = new THREE.PlaneGeometry(5, 5);
mesh = new THREE.Mesh(geometry, material);
mesh.position.z = -5;
scene = new THREE.Scene();
scene.add(mesh);
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
renderer = new THREE.WebGLRenderer({
alpha: true
});
document.body.appendChild( renderer.domElement );
renderer.setSize(width, height);
renderer.setClearColor( 0xffffff, 1 );
//renderer.render(scene, camera);
function render() {
//Finally, draw to the screen
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
Any help is truly appreciated.
ThreeJS/87
Edit:
I think I'm lacking more precision on my post.
This is the original full alpha image:
It might not show because its all white
And this is the same image with different transparencies on 4 quadrants:
This one too might not show because its all white
I got a helpful answer where I was told to make the alphaTest higher, but the problem is that doing that wipes out the transparent parts out of the images, and I need to conserve those parts.
Here is a copy of the codepen with the updated images and showing the same (but slight) grey edges:
codepen
Sorry for not being as precise the first time, any further help is even more appreciated.
Set alphaTest to 0.9.. or higher.. observe the improvement.
Your star texture has gray or black in the area outside the star, which is why you're seeing a gray halo. You can fix it by filling the image with white, (but not changing the alpha channel) in your image editing tool.
Also, you should upgrade to latest three.js (r95)
edit:
I'm not sure what your exact expectation is.. but there are many different settings that control alpha blending in THREE. There is renderer.premultipliedAlpha = true/false (defaults to true) and material.transparent = true/false; material.alphaTest is a threshold value to control at what level alpha is ignored completely. There are also the material.blending, .blendEquation .blendEquation, .blendEquationAlpha, blendDst and blendSrc. etc. etc. You probably need to read up on those.
https://threejs.org/docs/#api/materials/Material
For instance.. here is your texture with:
renderer.premultipliedAlpha = false;
notice the black border on one quadrant of your texture.
https://codepen.io/manthrax/pen/KBraNB
I have an instance of THREE.PlaneBufferGeometry that I apply an image texture to like this:
var camera, scene, renderer;
var geometry, material, mesh, light, floor;
scene = new THREE.Scene();
THREE.ImageUtils.loadTexture( "someImage.png", undefined, handleLoaded, handleError );
function handleLoaded(texture) {
var geometry = new THREE.PlaneBufferGeometry(
texture.image.naturalWidth,
texture.image.naturalHeight,
1,
1
);
var material = new THREE.MeshBasicMaterial({
map: texture,
overdraw: true
});
floor = new THREE.Mesh( geometry, material );
floor.material.side = THREE.DoubleSide;
scene.add( floor );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, texture.image.naturalHeight * A_BUNCH );
camera.position.z = texture.image.naturalWidth * 0.5;
camera.position.y = SOME_INT;
camera.lookAt(floor.position);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
appendToDom();
animate();
}
function handleError() {
console.log(arguments);
}
function appendToDom() {
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene,camera);
}
Here's the code pen: http://codepen.io/anon/pen/qELxvj?editors=001
( Note: ThreeJs "pollutes" the global scope, to use a harsh term, and then decorates THREE using a decorator pattern--relying on scripts loading in the correct order without using a module loader system. So, for brevity's sake, I simply copy-pasted the source code of a few required decorators into the code pen to ensure they load in the right order. You'll have to scroll down several thousand lines to the bottom of the code pen to play with the code that instantiates the plane, paints it and moves the camera. )
In the code pen, I simply lay the plane flat against the x-y axis, looking straight up the z-axis, as it were. Then, I slowly pan the camera down along the y-axis, continuously pointing it at the plane.
As you can see in the code pen, as the camera moves along the y-axis in the negative direction, the texture on the plane appears to develop a kink in it around West Texas.
Why? How can I prevent this from happening?
I've seen similar behaviour, not in three.js, not in a browser with webGL but with directX and vvvv; still, i think you'll just have to set widthSegments/heightSegments of your PlaneBufferGeometry to a higher level (>4) and you're set!
I want to spin a sphere, so I wonder if orbit controls could work for that.
However, code below won't work:
var geometry = new THREE.SphereGeometry(16, 16, 16);
var material = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var controls = new THREE.OrbitControls(mesh);
//then inside the animation loop
controls.update();
It seems like orbit controls only works when argument is camera. why?
You must pass the camera to the Orbit.
Like this:
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 0, 1000, 1000 );
var controls = new THREE.OrbitControls( camera );
This helps?
I don't think orbit controls work like that, the camera revolves around a point, it doesn't 'spin' that point. You can however change the target of the orbit controls to the sphere's position vector, allowing the camera to revolve around the sphere's position:
controls.target.copy(mesh.position);
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 );