threejs-earth
threejs-earth copied to clipboard
Different result than what is shown in the video
Hi! I tried to use this code in my Angular v17 project and essentially copied everything to my ngAfterViewInit function. However, when I run the program I get a different look than what we can see in the video (see pictures). It seems that something with the meshes is off, maybe opacity? Any idea how I can fix this? The rotation/animation works flawlessly and the clouds also move faster than the earth 👍
| Result from video | Result from copied code |
|---|---|
Here is the code of my component. As you can see, only thing I changed is the path to files. Edit: And removed the orbit controls.
import { Component, AfterViewInit } from '@angular/core';
import * as THREE from "three";
import { getFresnelMat } from '../../util/getFresnelMat';
import getStarfield from '../../util/getStartfield';
@Component({
selector: 'app-main',
standalone: true,
templateUrl: './main.component.html',
imports: []
})
export class MainComponent implements AfterViewInit {
ngAfterViewInit(): void {
const w = window.innerWidth;
const h = window.innerHeight;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);
const earthGroup = new THREE.Group();
earthGroup.rotation.z = -23.4 * Math.PI / 180;
scene.add(earthGroup);
const detail = 12;
const loader = new THREE.TextureLoader();
const geometry = new THREE.IcosahedronGeometry(1, detail);
const material = new THREE.MeshPhongMaterial({
map: loader.load("../../../assets/textures/00_earthmap1k.jpg"),
specularMap: loader.load("../../../assets/textures/02_earthspec1k.jpg"),
bumpMap: loader.load("../../../assets/textures/01_earthbump1k.jpg"),
bumpScale: 0.04,
});
const earthMesh = new THREE.Mesh(geometry, material);
earthGroup.add(earthMesh);
const lightsMat = new THREE.MeshBasicMaterial({
map: loader.load("../../../assets/textures/03_earthlights1k.jpg"),
blending: THREE.AdditiveBlending,
});
const lightsMesh = new THREE.Mesh(geometry, lightsMat);
earthGroup.add(lightsMesh);
const cloudsMat = new THREE.MeshStandardMaterial({
map: loader.load("../../../assets/textures/04_earthcloudmap.jpg"),
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending,
alphaMap: loader.load('../../../assets/textures/05_earthcloudmaptrans.jpg'),
// alphaTest: 0.3,
});
const cloudsMesh = new THREE.Mesh(geometry, cloudsMat);
cloudsMesh.scale.setScalar(1.003);
earthGroup.add(cloudsMesh);
const fresnelMat = getFresnelMat();
const glowMesh = new THREE.Mesh(geometry, fresnelMat);
glowMesh.scale.setScalar(1.01);
earthGroup.add(glowMesh);
const stars = getStarfield({ numStars: 2000 });
scene.add(stars);
const sunLight = new THREE.DirectionalLight(0xffffff);
sunLight.position.set(-2, 0.5, 1.5);
scene.add(sunLight);
function animate() {
requestAnimationFrame(animate);
earthMesh.rotation.y += 0.002;
lightsMesh.rotation.y += 0.002;
cloudsMesh.rotation.y += 0.0023;
glowMesh.rotation.y += 0.002;
stars.rotation.y -= 0.0002;
renderer.render(scene, camera);
}
animate();
function handleWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener('resize', handleWindowResize, false);
}
}
It appears that he is using the 4k images in the video. I similarly have poor rendering, I believe the 1k cloud image is the main culprit.
@cgrundman @SebastianKuehl , here u go, scroll down and get the 8K images, problem will be solved https://www.solarsystemscope.com/textures/
I copied the code into a Next.js component (everything inside useEffect, basically) and the animation works fine, but the rendering looks different from the video (see attached images). The Earth looks off — probably a color issue.
The fix is to set .colorSpace = THREE.SRGBColorSpace on each texture. By default, Three.js assumes linear color space, but most images (like JPG or PNG) are in sRGB, so the colors will look wrong unless you specify it.
Example:
const loader = new THREE.TextureLoader();
const texture = loader.load('/assets/textures/00_earthmap1k.jpg');
texture.colorSpace = THREE.SRGBColorSpace;
Apply that to every texture (map, bumpMap, specularMap, etc.). That alone makes the rendering match the one in the video.
Earth texture with colorSpace = THREE.SRGBColorSpace vs without:
With .SRGBColorSpace |
Without .SRGBColorSpace |
|---|---|
Hey @Csalcedo04, thanks for your comment, didn't know about this :)