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: