Three.js bloom layer issue - three.js

I already tried my best to find a solution to my problem but without any luck, hope for your help with this.
In my three.js file I have a moon that is surrounded by stars.
The moon is a simple sphere geometry and the stars are a particle system that use a texture. However they just look like flat circles flying around.
So far so good, the particles were flying all around the moon, some in front of it and some behind it. Exactly what I want.
Then I added a bloom effect and worked with layers. So the moon (layer 0) has no bloom and the particles (layer 1) has bloom added to it.
However that way all the star particles are flying behind the moon and not around it anymore.
Does anyone know how to fix this?
Thanks a ton in advance!
Preview video gif-file of the issue
Here is the js code:
const canvas = document.querySelector("canvas.webgl");
const scene = new THREE.Scene();
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
const camera = new THREE.PerspectiveCamera(
45,
sizes.width / sizes.height,
0.1,
1000
);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 5;
camera.layers.enable(1);
scene.add(camera);
const params = {
exposure: 1,
bloomStrength: 2,
bloomThreshold: 0,
bloomRadius: 0,
};
let composer, mixer;
const light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);
const sgeometry = new THREE.SphereGeometry(15, 32, 16);
const smaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
const ssphere = new THREE.Mesh(sgeometry, smaterial);
const loader1 = new THREE.TextureLoader();
const circle = loader1.load("a.png");
const particlesGeometry = new THREE.BufferGeometry();
const particlesCnt = 3000;
const posArray = new Float32Array(particlesCnt * 3);
for (i = 0; i < particlesCnt * 3; i++) {
posArray[i] = (Math.random() - 0.5) * (Math.random() * 20);
}
particlesGeometry.setAttribute(
"position",
new THREE.BufferAttribute(posArray, 3)
);
const mat = new THREE.PointsMaterial({
size: 0.05,
map: circle,
transparent: true,
opacity: 1,
alpha: 0.8,
alphaTest: 0.9,
alphaToCoverage: 0.91,
Blending: THREE.AdditiveBlending,
});
const particlesMesh = new THREE.Points(particlesGeometry, mat);
particlesMesh.position.set(0, 0, -1);
particlesMesh.layers.set(1);
scene.add(particlesMesh);
const geometry = new THREE.SphereBufferGeometry(1, 64, 64);
const material = new THREE.MeshPhongMaterial({
map: THREE.ImageUtils.loadTexture("moon.jpg"),
side: THREE.DoubleSide,
shininess: 0,
opacity: 1,
transparent: true,
});
const sphere = new THREE.Mesh(geometry, material);
sphere.rotation.set(0, -2.7, 0);
sphere.layers.set(0);
scene.add(sphere);
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true,
antialias: true,
});
renderer.autoClear = false;
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.toneMapping = THREE.LinearToneMapping;
const renderScene = new THREE.RenderPass(scene, camera);
const effectFXAA = new THREE.ShaderPass(THREE.FXAAShader);
effectFXAA.uniforms.resolution.value.set(
1 / window.innerWidth,
1 / window.innerHeight
);
const bloomPass = new THREE.UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight),
1.5,
0.4,
0.85
);
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;
composer = new THREE.EffectComposer(renderer);
composer.addPass(renderScene);
composer.addPass(effectFXAA);
composer.addPass(bloomPass);
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.toneMappingExposure = Math.pow(0.9, 4.0);
window.addEventListener("resize", () => {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});
const clock = new THREE.Clock();
const tick = () => {
window.requestAnimationFrame(tick);
const deltaTime = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
sphere.rotation.y = 0.08 * elapsedTime;
particlesMesh.rotation.y = 0.08 * elapsedTime;
renderer.clear();
camera.layers.set(1);
composer.render();
renderer.clearDepth();
camera.layers.set(0);
renderer.render(scene, camera);
};
tick();

The problem is probably that layer 0 (with the moon) is rendered AFTER layer 1 (with the stars). This makes the renderer paint the moon over the stars.
Try to change the order of the rendering so that layer 0 is first. Keep in mind that layer 1 must render in the composer, and layer 0 with the normal renderer. I think the code will be something like this:
renderer.clear();
camera.layers.set(0);
renderer.render(scene, camera);
renderer.clearDepth();
camera.layers.set(1);
composer.render();

Related

How to project a texture to curved surface?

Screen capture
I tried to make a 3/4 cylinder surface, and I made it from extruting by a ellipe path,
but when I tried to load a texture to the surface, It does not as I exprected: uniformly painted to the surface, it's stretched
I know it's about texture projection, But I dont know how to set options.
class EllipseCurve3 extends THREE.Curve {
ellipse = null
constructor (ellipse) {
super()
this.ellipse = ellipse
}
getPoint(t, optionalTarget = new THREE.Vector3()) {
const point = this.ellipse.getPoint(t, optionalTarget)
return new THREE.Vector3(
point.x,
point.y,
0
)
}
}
// Scene
const scene = new THREE.Scene();
var shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.moveTo(0, 1);
shape.lineTo(50, 1);
shape.moveTo(50, 0);
shape.lineTo(0, 0);
// var curve = new THREE.CatmullRomCurve3([
// new THREE.Vector3(0, 0, 50),
// new THREE.Vector3(-50, 0, 0),
// new THREE.Vector3(0, 0, -50)
// ]);
const arc = new THREE.EllipseCurve(
0,
0, // ax, aY
100,
100, // xRadius, yRadius
0,
1.5 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
),
path = new EllipseCurve3(arc)
geometry = new THREE.ExtrudeGeometry(shape, {
bevelEnabled: false,
extrudePath: path,
steps: 50,
depth: 5,
amount: 20,
material: 0,
extrudeMaterial: 1
});
// Set up lights
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.6);
directionalLight.position.set(100, 200, 100); // x, y, z
scene.add(directionalLight);
// Camera
const width = 200;
const height = width * (window.innerHeight / window.innerWidth);
const camera = new THREE.OrthographicCamera(
width / -2, // left
width / 2, // right
height / 2, // top
height / -2, // bottom
0.1, // near
1000 // far
);
camera.position.set(400, 400, 400);
camera.lookAt(0, 0, 0);
// Renderer
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
renderer.render(scene, camera);
// Add it to HTML
document.body.appendChild(renderer.domElement);
var textureLoader = new THREE.TextureLoader();
textureLoader.crossOrigin = true;
const picture = 'https://threejs.org/examples/textures/uv_grid_opengl.jpg'
textureLoader.load(picture, function(texture) {
// repeat pattern
texture.wrapS = texture.wrapT = THREE.MirroredRepeatWrapping;
// zoom in on pattern
texture.repeat.set(.01, .01);
// assign texture via MeshBasicMaterial
var material = new THREE.MeshBasicMaterial({
map: texture,
needsUpdate: true,
// transparent: true,
// premultipliedAlpha: true,
// side: THREE.DoubleSide,
// blending: THREE.AdditiveBlending
});
// var material = new THREE.MeshPhongMaterial({ color: 0x0048ff });
var mesh = new THREE.Mesh(geometry, material)
mesh.rotation.x = Math.PI / 2
// mesh.rotation.z = Math.PI / 2
scene.add(mesh)
scene.add(cube)
})
function render() {
renderer.render(scene, camera);
// Rotate out group
// svgGroup.rotation.y -= 0.005
controls.update();
requestAnimationFrame(render);
}
render();
Code here
https://codepen.io/mike-xu/pen/RwQeEXJ
"I know it's about texture projection" - It's about computing UV, based on vertices coordinates.
CylinderGeometry also may help to achieve the result you described. With less code, and more convenient and predictable way.
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three#0.136.0/examples/jsm/controls/OrbitControls.js";
console.clear();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 10, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", event => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
let controls = new OrbitControls(camera, renderer.domElement);
scene.add(new THREE.AxesHelper(10));
let g = new THREE.CylinderGeometry(5, 5, 5, 100, 20, true, 0, Math.PI * 1.5);
let m = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide,
map: new THREE.TextureLoader().load(
"https://threejs.org/examples/textures/uv_grid_opengl.jpg",
tex => {
tex.wrapS = tex.wrapT = THREE.MirroredRepeatWrapping;
tex.repeat.set(3, 1);
}
)
});
let c = new THREE.Mesh(g, m);
scene.add(c);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
</script>

How to animate a threeJS object using GSAP?

I have been learning threeJS just recently and can't get passed a problem. I tried to animate a extruded triangle using the GSAP library. It is just a simple animation to have the triangle move to the right but it seems I did something wrong. Any help is much appreciated.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create Triangles
var material = new THREE.MeshPhongMaterial({
color: 0xf6c12a,
shininess: 70
});
var shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.lineTo(2, 3);
shape.lineTo(4, 0);
shape.lineTo(0, 0);
var extrudeSettings = {
steps: 5,
depth: 1,
bevelEnabled: true,
bevelThickness: 0.3,
bevelSize: 0.5,
bevelOffset: 0,
bevelSegments: 1
};
var geometry = new THREE.ExtrudeBufferGeometry(shape, extrudeSettings);
// Sets the origin to the center of geometry for rotation
geometry.center();
var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = -5;
mesh.scale.set(1.5, 1.5, 1.5);
scene.add(mesh);
gsap.to(mesh, { duration: 2, x: 300 });
camera.position.z = 5;
// Background
var geometry = new THREE.PlaneGeometry(1000, 1000, 1);
var material = new THREE.MeshPhysicalMaterial({ color: 0x444444 });
var plane = new THREE.Mesh(geometry, material);
plane.position.z = -50;
scene.add(plane);
// Lighting
var ambientLight = new THREE.AmbientLight(0xffffff, 0.55);
scene.add(ambientLight);
var pointLight1 = new THREE.PointLight(0xf9eac8, 1, 100);
pointLight1.position.set(5, 10, 0);
pointLight1.castShadow = true;
pointLight1.shadow.camera.top = 20;
scene.add(pointLight1);
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
Here is the link to Codepen
Tried to put the gsap code into different position but maybe that's not the problem.
gsap.to(mesh.position, { duration: 2, x: 300 });
the value that you want to change is mesh.position.x not mesh.x
just add .position it will work

Rendered object looks flat even with shadows

I'm a three.js newb. I've been playing around with it for a couple of days and haven't been able to figure out how to make my objects look more realistic. I suspect there's no simple answer for this question, but is there anything I can do to improve my rendering quality without going into the depth of "rendering science"? Maybe I'm missing some configs. Thank you for any advice!
Here's the relevant code used in rendering a kitchen cabinet frame.
this.renderer = new THREE.WebGLRenderer({ antialias: true })
this.renderer.setSize(this.container.offsetWidth, this.container.offsetHeight)
this.renderer.sortObjects = false
this.renderer.setClearColor(0xf0f0f0)
this.renderer.gammaFactor = 2.2
this.renderer.gammaOutput = true
this.renderer.setPixelRatio(window.devicePixelRatio)
this.renderer.shadowMap.enabled = true
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
const light = new THREE.AmbientLight(0xffffff, 0.8)
const light2 = new THREE.PointLight(0xffffff, 0.3)
light2.position.set(400, 400, 400)
light2.shadow.camera.near = 10
light2.shadow.camera.far = 10000
light2.shadow.mapSize.width = 2048
light2.shadow.mapSize.height = 2048
light2.castShadow = true
this.scene.add(light2)
this.scene.add(light)
const material = new THREE.MeshStandardMaterial({ color: 0xffffff, metalness: 0, roughness: 0 })
let scene, camera, controls, ambient, point, loader, renderer, container, stats;
const targetRotation = 0;
const targetRotationOnMouseDown = 0;
const mouseX = 0;
const mouseXOnMouseDown = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
init();
animate();
var box, b1, b2, b3;
function init() {
// Create a scene which will hold all our meshes to be rendered
scene = new THREE.Scene();
// Create and position a camera
camera = new THREE.PerspectiveCamera(
60, // Field of view
window.innerWidth / window.innerHeight, // Aspect ratio
/*window.innerWidth / -8,
window.innerWidth / 8,
window.innerHeight / 8,
window.innerHeight / -8,
*/
0.1, // Near clipping pane
1000 // Far clipping pane
);
scene.add(camera)
// Reposition the camera
camera.position.set(0, 5, 10);
// Point the camera at a given coordinate
camera.lookAt(new THREE.Vector3(0, 0, 0));
// Add orbit control
controls = new THREE.OrbitControls(camera);
controls.target.set(0, -0.5, 0);
controls.update();
// Add an ambient lights
ambient = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambient);
// Add a point light that will cast shadows
point = new THREE.PointLight(0xffffff, 1);
point.position.set(25, 50, 25);
point.castShadow = true;
point.shadow.mapSize.width = 1024;
point.shadow.mapSize.height = 1024;
scene.add(point);
group = new THREE.Group();
group.position.y = 0;
scene.add(group);
rotationAnchor = new THREE.Object3D()
group.add(rotationAnchor);
box = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshStandardMaterial({
color: 'grey'
}))
b1 = box.clone();
b2 = box.clone();
b3 = box.clone();
b3.material = b3.material.clone()
b3.material.color.set('red')
group.add(box);
group.add(b1);
b1.position.y += 1
group.add(b2);
b2.position.z += 1
rotationAnchor.add(b3);
rotationAnchor.position.set(0.5, 0.5, 1.5)
b3.position.set(-.5, -.5, -.5)
// Create a renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
// Set size
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Set color
renderer.setClearColor(0xf8a5c2);
renderer.gammaOutput = true;
// Enable shadow mapping
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Append to the document
container = document.createElement("div");
document.body.appendChild(container);
document.body.appendChild(renderer.domElement);
// Add resize listener
window.addEventListener("resize", onWindowResize, false);
// Enable FPS stats
stats = new Stats();
container.appendChild(stats.dom);
var gui = new dat.GUI({
height: 5 * 32 - 1
});
let params = {
'test': 4,
'bevelThickness': 1,
'bevelSize': 1.5,
'bevelSegments': 3
}
gui.add(params, 'test', 0, 10).onChange(val => {
test = val
})
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
rotationAnchor.rotation.z = (Math.cos(performance.now() * 0.001) * Math.PI * 0.25) + (Math.PI * 1.25)
requestAnimationFrame(animate);
// Re-render scene
renderer.render(scene, camera);
// Update stats
stats.update();
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.2/dat.gui.min.js"></script>

Moving an object using three.js

I am very much new to this three.js. I want to create two cubes. I am least interested in its animation. So, i want cube 1 to move towards cube 2 without any keyboard inputs. I am also providing image for better understanding.
Thanks in advance
On possibility to animate objects, is to use THREE.Tween
Create the 2 cubes:
var material1 = new THREE.MeshPhongMaterial({color:'#2020ff'});
var geometry1 = new THREE.BoxGeometry( 1, 1, 1 );
cube1 = new THREE.Mesh(geometry1, material1);
cube1.position.set(0.0, 0.0, 2.0);
var material2 = new THREE.MeshPhongMaterial({color:'#ff2020'});
var geometry2 = new THREE.BoxGeometry( 1, 1, 1 );
cube2 = new THREE.Mesh(geometry2, material2);
cube2.position.set(2.0, 0.0, 0.0);
Create a Tween, which rotates the cube and continuously restarts:
tweenStart = { value: 0 };
var finish = { value: Math.PI/2 };
cubeTween = new TWEEN.Tween(tweenStart);
cubeTween.to(finish, 3000)
cubeTween.onUpdate(function() {
cube1.position.set(0.0, 0.0, 0.0);
cube1.rotation.y = tweenStart.value;
cube1.translateZ( 2.0 );
});
cubeTween.onComplete( function() {
tweenStart.value = 0;
requestAnimationFrame(function() {
cubeTween.start();
});
});
cubeTween.start();
(function onLoad() {
var container, loader, camera, scene, renderer, controls, cube1, cube2, cubeTween, tweenStart;
init();
animate();
animateCube();
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 6, 0);
camera.lookAt( 0, 0, 0 );
loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set(1,2,1.5);
scene.add( directionalLight );
controls = new THREE.OrbitControls(camera);
addGridHelper();
createModel();
}
function createModel() {
var material1 = new THREE.MeshPhongMaterial({color:'#2020ff'});
var geometry1 = new THREE.BoxGeometry( 1, 1, 1 );
cube1 = new THREE.Mesh(geometry1, material1);
cube1.position.set(0.0, 0.0, 2.0);
var material2 = new THREE.MeshPhongMaterial({color:'#ff2020'});
var geometry2 = new THREE.BoxGeometry( 1, 1, 1 );
cube2 = new THREE.Mesh(geometry2, material2);
cube2.position.set(2.0, 0.0, 0.0);
scene.add(cube1);
scene.add(cube2);
tweenStart = { value: 0 };
var finish = { value: Math.PI/2 };
cubeTween = new TWEEN.Tween(tweenStart);
cubeTween.to(finish, 3000)
cubeTween.onUpdate(function() {
cube1.position.set(0.0, 0.0, 0.0);
cube1.rotation.y = tweenStart.value;
cube1.translateZ( 2.0 );
});
cubeTween.onComplete( function() {
tweenStart.value = 0;
requestAnimationFrame(function() {
cubeTween.start();
});
});
cubeTween.start();
}
function addGridHelper() {
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
TWEEN.update();
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.js"></script>
<div id="container"></div>
Alternatively you can slightly change the position of the cube by changing the position property of the cube in the animate function:
function animate() {
requestAnimationFrame(animate);
if ( cube1.position.z > 0.0 ) {
cube1.position.set(0.0, 0.0, cube1.position.z-0.01);
} else if ( cube1.position.x < 2.0 ) {
cube1.position.set(cube1.position.x+0.01, 0.0, 0.0);
} else {
cube1.position.set(0.0, 0.0, 2.0);
}
render();
}
(function onLoad() {
var container, loader, camera, scene, renderer, controls, cube1, cube2, cubeTween, tweenStart;
init();
animate();
animateCube();
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 6, 0);
camera.lookAt( 0, 0, 0 );
loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set(1,2,1.5);
scene.add( directionalLight );
controls = new THREE.OrbitControls(camera);
addGridHelper();
createModel();
}
function createModel() {
var material1 = new THREE.MeshPhongMaterial({color:'#2020ff'});
var geometry1 = new THREE.BoxGeometry( 1, 1, 1 );
cube1 = new THREE.Mesh(geometry1, material1);
cube1.position.set(0.0, 0.0, 2.0);
var material2 = new THREE.MeshPhongMaterial({color:'#ff2020'});
var geometry2 = new THREE.BoxGeometry( 1, 1, 1 );
cube2 = new THREE.Mesh(geometry2, material2);
cube2.position.set(2.0, 0.0, 0.0);
scene.add(cube1);
scene.add(cube2);
}
function addGridHelper() {
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
if ( cube1.position.z > 0.0 ) {
cube1.position.set(0.0, 0.0, cube1.position.z-0.01);
} else if ( cube1.position.x < 2.0 ) {
cube1.position.set(cube1.position.x+0.01, 0.0, 0.0);
} else {
cube1.position.set(0.0, 0.0, 2.0);
}
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
There are a few different ways you could do this.
It will also be easier to answer this by assuming axes and both cube's starting position.
Let's say cube1 position is:
x: 0
y: 0
z: 0
Cube2 position is:
x: 10
y: 20
z: 0
In the render loop, move cube1 along the y-axis until it reaches the same value as cube2 (20), then move cube1 along the x-axis until it reaches cube2 x position. So cube1 would then be sitting on top of cube2. You would need the code to move cube1 to be present, but only run when certain conditions are met.
E.g, only move in the y-axis if cube1.position.y is less than or equal to cube2.position.y
Movement speed can be increased or decreased by changing the increment value. So an update on the y-axis could look like this:
cube1.position.y += 0.1;
This way could be harder to manage though, as you will need to constantly check the cube1 position in relation to cube2, and because the cube needs to move in two directions this could get messy in the long-run.
You can see an example of this update in the loop concept here - https://jsfiddle.net/f2Lommf5/
I would look at using an animation library such as Tween.js or Greensock which in my opinion would be much better suited. You can specify an axis to move along, the start and end position, animation duration and easing. When the animation on the y-axis is complete, you can start the animation on the x-axis.
Some useful links:
Tween.js - http://learningthreejs.com/blog/2011/08/17/tweenjs-for-smooth-animation/
Greensock - http://www.kadrmasconcepts.com/blog/2012/05/29/greensock-three-js/

really weird ghosty shadows using three.js

I'm using three.js to make some solar system, all my objects are sphere (suns and planets), but I found this really weird and ghosty square shadow:
Another ghost shadow seems to be that, the shadow that sphere A casts on sphere B, appears on both the front and back side of sphere B, like this:
I am so confused since I don't really remember create any square stuff and I've checked my code for like million times without any finding.
Finally, I dismissed all the lights in the world, and set the background to light color, it appears:
But when I move my camera to the back of it, it just disappears, like a "1-dimension" square created by some high-level creature from the universe.
This is my final project which is due next week, I really don't know how to explain this to my professor.
Appreciate any help!
Thanks a lot!
below is my code that creates objects:
function init() {
container = document.createElement('div');
document.body.appendChild(container);
renderer = new THREE.WebGLRenderer({
antialias : true, alpha: true
});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.shadowMapEnabled = true;
container.appendChild(renderer.domElement);
scene = new THREE.Scene();
scene.updateMatrixWorld(true);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 1000 );
camera.position.set(5,5,5);
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.staticMoving = false;
controls.dynamicDampingFactor = 0.2;
var light = new THREE.AmbientLight( 0x222222 );
scene.add( light ); // this is the light I tried to close
var light = new THREE.DirectionalLight( 0xffffff, 0 );
light.position.set(0,0,5);
scene.add( light ); // this is the light I tried to close
light.castShadow = true;
light.shadowCameraNear = 0.01;
light.shadowCameraFar = 15;
light.shadowCameraFov = 45;
light.shadowCameraLeft = -1;
light.shadowCameraRight = 1;
light.shadowCameraTop = 1;
light.shadowCameraBottom= -1;
//light.shadowCameraVisible = true
light.shadowBias = 0.001;
light.shadowDarkness = 0.2;
light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;
//////////////////////////////////////////////////////////////////////////////////
// render the scene //
//////////////////////////////////////////////////////////////////////////////////
onRenderFcts.push(function(){
controls.update();
renderer.render( scene, camera );
});
window.addEventListener('keydown', onKeyDown, false);
renderer.domElement.addEventListener( 'mousemove', onMouseMove, false );
renderer.domElement.addEventListener( 'click', onMouseClick, false );
}
function createSun (){
var geometry = new THREE.SphereGeometry(0.5, 32, 32)
var texture = THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/sunmap.jpg')
var material = new THREE.MeshPhongMaterial({
map : texture,
bumpMap : texture,
bumpScale: 0.05,
emissive: new THREE.Color('#ff9933'),
specular: new THREE.Color('#ffff66'),
shininess: 800,
wireframeLinewidth: 500
})
var mesh = new THREE.Mesh(geometry, material)
mesh.receiveShadow = true;
mesh.castShadow = true;
mesh.matrixWorldNeedsUpdate = true;
return mesh
}
function createMoon (){
var geometry = new THREE.SphereGeometry(0.5, 32, 32)
var material = new THREE.MeshPhongMaterial({
map : THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/moonmap1k.jpg'),
bumpMap : THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/moonbump1k.jpg'),
bumpScale: 0.002,
})
var mesh = new THREE.Mesh(geometry, material)
return mesh
}
function add_objects() {
// star field
var geometry = new THREE.SphereGeometry(900, 32, 32);
var material = new THREE.MeshBasicMaterial({
map : THREE.ImageUtils.loadTexture('images/earthcloudmap.jpg'),
side : THREE.BackSide
});
var starSphere = new THREE.Mesh(geometry, material);
scene.add(starSphere);
// reference points
originPoint = new THREE.Object3D();
scene.add(originPoint);
onRenderFcts.push(function (delta, now) {
originPoint.rotation.x += rotateFactor * delta;
originPoint.rotation.z += rotateFactor * delta;
});
sunsBasePoint = new THREE.Object3D();
originPoint.add(sunsBasePoint);
onRenderFcts.push(function (delta, now) {
sunsBasePoint.rotation.y += rotateFactor * delta;
sunsBasePoint.rotation.z += rotateFactor * delta;
});
// stars
sun1 = createSun();
sun1.name = 'sun1';
sun1.position.set(0,0,-1.5);
sunsBasePoint.add(sun1);
onRenderFcts.push(function (delta, now) {
sun1.rotation.y -= 1/2 * delta;
sun1.rotation.z += 1/4 * delta;
});
objects.push(sun1);
sun2 = createSun();
sun2.name = 'sun2';
sun2.position.set(1,-1.5,0);
sun2.scale.multiplyScalar(0.8)
sunsBasePoint.add(sun2);
onRenderFcts.push(function (delta, now) {
sun2.rotation.x -= 1/4 * delta;
sun2.rotation.y += 1/8 * delta;
});
objects.push(sun2);
sun3 = createSun();
sun3.name = 'sun3';
sun3.position.set(-1,1,1.5);
sun3.scale.multiplyScalar(1.5);
sunsBasePoint.add(sun3);
onRenderFcts.push(function (delta, now) {
sun3.rotation.y -= 1/8 * delta;
sun3.rotation.x += 1/4 * delta;
});
objects.push(sun3);
threeBodyPlanet = createMoon();
threeBodyPlanet.name = "Three Body Planet";
threeBodyPlanet.position.set(0.5,-0.5,0.5);
threeBodyPlanet.scale.multiplyScalar(1/5);
threeBodyPlanet.receiveShadow = true;
threeBodyPlanet.castShadow = true;
originPoint.add(threeBodyPlanet);
objects.push(threeBodyPlanet);
}
function debug() {
var debugaxis = function(axisLength){
//Shorten the vertex function
function v(x,y,z){
return new THREE.Vertex(new THREE.Vector3(x,y,z));
}
//Create axis (point1, point2, colour)
function createAxis(p1, p2, color){
var line, lineGeometry = new THREE.Geometry(),
lineMat = new THREE.LineBasicMaterial({color: color, lineWidth: 1});
lineGeometry.vertices.push(p1, p2);
line = new THREE.Line(lineGeometry, lineMat);
scene.add(line);
}
createAxis(v(-axisLength/25, 0, 0), v(axisLength, 0, 0), 0xFF0000);
createAxis(v(0, -axisLength/25, 0), v(0, axisLength, 0), 0x00FF00);
createAxis(v(0, 0, -axisLength/25), v(0, 0, axisLength), 0x0000FF);
};
//To use enter the axis length
debugaxis(100);
// lens flares
var textureFlare0 = THREE.ImageUtils.loadTexture( "lensflare0.png" );
var textureFlare2 = THREE.ImageUtils.loadTexture( "lensflare2.png" );
var textureFlare3 = THREE.ImageUtils.loadTexture( "lensflare3.png" );
addLight( 0.55, 0.9, 0.5, 0, 0, 100 );
//addLight( 0.08, 0.8, 0.5, 0, 0, -10 );
//addLight( 0.995, 0.5, 0.9, 50, 50, -10 );
function addLight( h, s, l, x, y, z ) {
var light = new THREE.PointLight( 0xffffff, 1.5, 4500 );
light.color.setHSL( h, s, l );
light.position.set( x, y, z );
scene.add( light );
var flareColor = new THREE.Color( 0xffffff );
flareColor.setHSL( h, s, l + 0.5 );
var lensFlare = new THREE.LensFlare( textureFlare0, 700, -0.1, THREE.AdditiveBlending, flareColor );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 60, 0.6, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 70, 0.7, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 120, 0.9, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 70, 1.0, THREE.AdditiveBlending );
lensFlare.customUpdateCallback = lensFlareUpdateCallback;
lensFlare.position = light.position;
lensFlare.size = 70;
scene.add( lensFlare );
}
function lensFlareUpdateCallback( object ) {
var f, fl = object.lensFlares.length;
var flare;
var vecX = -object.positionScreen.x * 2;
var vecY = -object.positionScreen.y * 2;
//var size = object.size ? object.size : 1000;
for( f = 0; f < fl; f++ ) {
flare = object.lensFlares[ f ];
flare.x = object.positionScreen.x + vecX * flare.distance;
flare.y = object.positionScreen.y + vecY * flare.distance;
//flare.scale = size / camera.distance;
flare.rotation = 0;
}
object.lensFlares[ 2 ].y += 0.025;
object.lensFlares[ 3 ].rotation = object.positionScreen.x * 0.5 + THREE.Math.degToRad( 45 );
};
}
-------------updating-------------
Thanks for yaku's help, I found that the weird square is indeed because of the camera shadow,like in the pics below:
After I increased the shadow parameters, the square shadow seems to be gone, but the remaining shadows on the back of the spheres are still kind of weird in its texture, like this:
It looks like very low resolution shadow made of small squares, why?
Thanks a lot!
------one more question------
All yaku said works!
But I found out there's no shadows of the spheres themselves.
I called
mesh.castShadow = mesh.receiveShadow = true;
every time I create the spheres.
I remember there were these shadows now they are gone...
What might the reason of it?
Thanks!
Not sure, but have you checked the shadow camera dimensions? Looks like the frustum of the shadow camera could be too small, and what you are seeing could be everything inside the frustum is in shadow and the rest unaffected. The light square could be some weird remnant of the shadow camera, shadow maps can be unwieldy..
Set light.shadowCameraVisible = true; and adjust the other shadow parameters so that the box encapsulates the whole scene.

Resources