<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>感觉要被吸进去啦!</title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://cdn.skypack.dev/three@0.139.2';
import orbitControlsEs6 from 'https://cdn.skypack.dev/orbit-controls-es6@2.0.1';
const canvasContainer = document.getElementById('container');
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0, -200, 0);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x080808);
document.body.appendChild(renderer.domElement);
new orbitControlsEs6(camera, renderer.domElement);
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
const textureLoader = new THREE.TextureLoader();
textureLoader.load(
'https://images.unsplash.com/photo-1631519952398-5b1d76b946e8?q=80&w=3087&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
function (texture) {
const vertexShader = `
varying vec2 vUv;
uniform float u_time;
varying float vElevation;
varying vec3 vNormal;
float oscillate(float time, float minVal, float maxVal) {
float sineWave = sin(time);
float normalizedSine = (sineWave + 1.0) / 2.0;
return mix(minVal, maxVal, normalizedSine);
}
void main() {
vUv = uv;
vNormal = normalize(normalMatrix * normal);
vec3 newPosition = vec3(position.x, position.y * oscillate(u_time/4.0, 4.0,15.0), position.z);
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
}
`;
const fragmentShader = `
varying vec2 vUv;
uniform sampler2D u_texture;
uniform float u_time;
varying vec3 vNormal;
vec3 palette(float t, float u_time) {
vec3 a = vec3(0.5 + 0.5 * sin(u_time * 6.28318), 0.5, 0.9);
vec3 b = vec3(0.9, 0.5 + 0.5 * cos(u_time * 6.28318), 0.5);
vec3 c = vec3(1.0, 1.0, 1.0);
vec3 d = vec3(0.25, 0.4, 0.55 + 0.45 * sin(u_time * 6.28318));
return a + b * cos(6.28318 * (c * t + d));
}
float oscillate(float time, float minVal, float maxVal) {
float sineWave = sin(time);
float normalizedSine = (sineWave + 1.0) / 2.0;
return mix(minVal, maxVal, normalizedSine);
}
void main() {
vec2 animatedUv = (vUv.y + vUv.x) + vec2(u_time * -0.02, vUv.y);
vec4 color = texture2D(u_texture, mod(animatedUv, 1.0));
float blackThreshold = 0.5;
float intensity = max(color.r, max(color.g, color.b));
if (intensity < blackThreshold) {
discard;
}
gl_FragColor = color * vec4(palette(vUv.y, oscillate(u_time/5.0, 0.0, 1.0)), 1.0);
}
`;
const radius = 50;
const segments = 512;
const rings = 512;
const geometry = new THREE.SphereGeometry(radius, segments, rings);
geometry.uvsNeedUpdate = true;
const customMaterial = new THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
wireframe: false,
side: THREE.DoubleSide,
uniforms: {
u_time: { value: 0.0 },
u_texture: { value: texture },
},
});
const sphere = new THREE.Mesh(geometry, customMaterial);
scene.add(sphere);
const bgVertex = `
varying vec2 vUv;
uniform float u_time;
varying float vElevation;
varying vec3 vNormal;
float oscillate(float time, float minVal, float maxVal) {
float sineWave = sin(time);
float normalizedSine = (sineWave + 1.0) / 2.0;
return mix(minVal, maxVal, normalizedSine);
}
void main() {
vUv = uv;
vNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const bgFragment = `
varying vec2 vUv;
uniform float u_time;
varying vec3 vNormal;
void main() {
gl_FragColor = vec4(1.0);
}
`;
const backgroundShader = new THREE.ShaderMaterial({
vertexShader: bgVertex,
fragmentShader: bgFragment,
side: THREE.DoubleSide,
uniforms: {
u_time: { value: 0.0 },
},
});
const background = new THREE.SphereGeometry(800, 1024, 1024);
const backgroundMesh = new THREE.Mesh(background, backgroundShader);
backgroundMesh.position.z = -1;
scene.add(backgroundMesh);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(10, 10, 10);
scene.add(directionalLight);
function animate() {
requestAnimationFrame(animate);
customMaterial.uniforms.u_time.value = performance.now() / 1000;
backgroundShader.uniforms.u_time.value = performance.now() / 1000;
renderer.render(scene, camera);
}
animate();
}
);
</script>
</body>
</html>