-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMars.js
108 lines (92 loc) · 3.86 KB
/
Mars.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import * as THREE from 'three';
export class Mars {
constructor(scene, onLoadingComplete) {
this.scene = scene;
this.globe = null;
this.isWet = true;
this.onLoadingComplete = onLoadingComplete;
this.setupLighting();
this.loadTextures();
}
loadTextures() {
const loadingManager = new THREE.LoadingManager();
const textureLoader = new THREE.TextureLoader(loadingManager);
loadingManager.onProgress = (url, itemsLoaded, itemsTotal) => {
const progress = (itemsLoaded / itemsTotal * 100).toFixed(0);
this.updateLoadingMessage(`Loading: ${progress}%`);
};
loadingManager.onLoad = () => {
this.updateLoadingMessage('');
if (this.onLoadingComplete) this.onLoadingComplete();
};
this.wetTexture = textureLoader.load('assets/wet_mars_5.png');
this.dryTexture = textureLoader.load('assets/mars_8k_color.jpg');
const normal = textureLoader.load('assets/mars_8k_normal.jpg');
this.wetTexture.encoding = THREE.sRGBEncoding;
this.dryTexture.encoding = THREE.sRGBEncoding;
// Create a custom shader material
this.material = new THREE.ShaderMaterial({
uniforms: {
colorMap: { value: this.wetTexture },
normalMap: { value: normal },
normalScale: { value: new THREE.Vector2(1, 1) }
},
vertexShader: `
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vUv = uv;
vNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform vec2 normalScale;
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vec3 normal = texture2D(normalMap, vUv).rgb * 2.0 - 1.0;
normal.xy *= normalScale;
normal = normalize(normal);
// Simulate ambient occlusion
float ao = (normal.z + 1.0) * 0.5;
ao = smoothstep(0.0, 1.0, ao);
ao = mix(0.8, 1.0, ao); // Adjust these values to control the shadow intensity
vec3 color = texture2D(colorMap, vUv).rgb;
gl_FragColor = vec4(color * ao, 1.0);
}
`
});
const geometry = new THREE.SphereGeometry(1, 128, 128);
this.globe = new THREE.Mesh(geometry, this.material);
this.scene.add(this.globe);
}
updateLoadingMessage(message) {
const loadingDiv = document.getElementById('loading-message');
if (loadingDiv) {
loadingDiv.textContent = message;
}
}
setupLighting() {
// Remove previous lights
this.scene.remove(...this.scene.children.filter(child => child instanceof THREE.Light));
// Add ambient light
const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
this.scene.add(ambientLight);
// Add directional light (sun-like)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 3, 5);
this.scene.add(directionalLight);
// Add subtle warm fill light
const fillLight = new THREE.PointLight(0xffad70, 0.3);
fillLight.position.set(-5, 0, -5);
this.scene.add(fillLight);
}
setWetness(isWet) {
this.isWet = isWet;
this.material.uniforms.colorMap.value = this.isWet ? this.wetTexture : this.dryTexture;
this.material.needsUpdate = true;
}
}