Three.js 赛博空间高拟真黑洞引力透镜(Gravitational Lensing):基于空间弯曲着色器
Three.js 赛博空间高拟真黑洞引力透镜Gravitational Lensing基于空间弯曲着色器在《星际穿越》Interstellar等顶级科幻作品中巨型黑洞Black Hole周围的时空弯曲与引力透镜效应Gravitational Lensing是最具宇宙宏大感与物理震撼力的视觉奇观黑洞中央是一片吞噬一切光线的绝对事件视界Event Horizon / 纯黑核心紧随其后的是一道以数倍相对论速度剧烈旋转的高能发光吸积盘Accretion Disk宇宙深处的背景星光在穿过黑洞强引力场时被弯曲折射为壮丽的爱因斯坦环Einstein Ring与多重扭曲光弧。传统的 3D 模型无法表现“背景光线被弯曲”的物理特性。通过编写自定义的Three.js 引力透镜后处理着色器Gravitational Lensing Post-processing Shader / GLSL我们可以在浏览器端利用广义相对论光线偏折公式以纯 60 FPS 满帧实时渲染出令人屏息的赛博宇宙黑洞奇观一、引力透镜光线弯曲与爱因斯坦环物理模型拓扑graph LR BackgroundStars[背景赛博星空与星系纹理 (Background Texture)] -- PostShader[GPU 引力透镜片元着色器 (Screen-space Lens Shader)] subgraph 广义相对论光线偏折计算 (Relativistic Ray Deflection) PostShader -- CenterDist[计算当前屏幕像素 UV 到黑洞屏幕中心 (x0, y0) 的距离 r] CenterDist -- Schwarzschild[史瓦西半径判定: 若 r r_event - 输出绝对纯黑 (事件视界)] CenterDist -- LensFormula[偏折方程: UV_offset normalize(UV - Center) * (G * M / r^2)] end LensFormula -- DistortionSample[利用偏折后的 UV 重新采样背景星空纹理] DistortionSample -- AccretionDisk[叠加吸积盘发光贴图 多普勒红移调色] AccretionDisk -- Output[输出逼真的爱因斯坦环与黑洞引力透镜画面]二、引力透镜后处理着色器GLSL 实现// shaders/cyberBlackHoleLensingShader.ts import * as THREE from three; export const CyberBlackHoleLensingShader { uniforms: { tDiffuse: { value: null }, // 场景与背景星空纹理 uBlackHoleScreenPos: { value: new THREE.Vector2(0.5, 0.5) }, // 黑洞屏幕归一化坐标 uEventHorizonRadius: { value: 0.08 }, // 事件视界纯黑半径 uLensingStrength: { value: 0.045 }, // 引力透镜弯曲强度 uTime: { value: 0 }, uResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) }, }, vertexShader: varying vec2 vUv; void main() { vUv uv; gl_Position projectionMatrix * modelViewMatrix * vec4(position, 1.0); } , fragmentShader: uniform sampler2D tDiffuse; uniform vec2 uBlackHoleScreenPos; uniform float uEventHorizonRadius; uniform float uLensingStrength; uniform float uTime; uniform vec2 uResolution; varying vec2 vUv; void main() { // 修正屏幕宽高比 (Aspect Ratio Correction) float aspect uResolution.x / uResolution.y; vec2 aspectCorrectedUv vec2(vUv.x * aspect, vUv.y); vec2 aspectCorrectedCenter vec2(uBlackHoleScreenPos.x * aspect, uBlackHoleScreenPos.y); // 1. 计算当前像素到黑洞中心的二维欧氏距离 vec2 delta aspectCorrectedUv - aspectCorrectedCenter; float dist length(delta); // 2. 核心判定 A: 若处于事件视界 (Event Horizon) 内部光线无法逃逸 - 绝对纯黑 if (dist uEventHorizonRadius) { gl_FragColor vec4(0.0, 0.0, 0.0, 1.0); return; } // 3. 核心判定 B: 广义相对论引力透镜光线偏折计算 (爱因斯坦偏角) // 距离中心越近偏折角越剧烈 float normalizedDist dist - uEventHorizonRadius; float deflection uLensingStrength / (normalizedDist 0.01); // 计算弯曲后的新采样坐标 vec2 distortedUv vUv - normalize(delta) * deflection; // 4. 采样偏折后的背景星空 vec4 sceneColor texture2D(tDiffuse, distortedUv); // 5. 在事件视界边缘激发出高能光子环 (Photon Sphere Glow) float photonRing 0.0; if (dist uEventHorizonRadius dist uEventHorizonRadius * 1.35) { photonRing pow(1.0 - (dist - uEventHorizonRadius) / (uEventHorizonRadius * 0.35), 3.0); } vec3 finalColor sceneColor.rgb; // 叠加赛博青/亮金色光子环 finalColor vec3(0.0, 0.95, 1.0) * photonRing * 1.8; gl_FragColor vec4(finalColor, sceneColor.a); } , };三、场景装配与吸积盘动态旋转装配// scene/cyberBlackHoleStage.ts import * as THREE from three; import { EffectComposer } from three/examples/jsm/postprocessing/EffectComposer.js; import { RenderPass } from three/examples/jsm/postprocessing/RenderPass.js; import { ShaderPass } from three/examples/jsm/postprocessing/ShaderPass.js; import { CyberBlackHoleLensingShader } from ../shaders/cyberBlackHoleLensingShader; export function setupBlackHoleScene(container: HTMLElement) { const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 2, 10); const renderer new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); container.appendChild(renderer.domElement); // 1. 创建发光旋转吸积盘网格 (Accretion Disk Mesh) const diskGeo new THREE.RingGeometry(1.2, 3.8, 64); const diskMat new THREE.MeshBasicMaterial({ color: 0x00f3ff, side: THREE.DoubleSide, transparent: true, opacity: 0.85, blending: THREE.AdditiveBlending, }); const accretionDisk new THREE.Mesh(diskGeo, diskMat); accretionDisk.rotation.x Math.PI * 0.4; scene.add(accretionDisk); // 2. 组装引力透镜后处理合成器 const composer new EffectComposer(renderer); composer.addPass(new RenderPass(scene, camera)); const lensingPass new ShaderPass(CyberBlackHoleLensingShader); composer.addPass(lensingPass); return { composer, update: (delta: number) { // 旋转吸积盘 accretionDisk.rotation.z delta * 0.6; lensingPass.uniforms.uTime.value delta; composer.render(); }, }; }四、黑洞引力透镜三大极客优化法则屏幕坐标系自适应映射Screen-space Center Projection若黑洞在三维世界中移动将黑洞的世界坐标通过worldPosition.project(camera)动态计算为屏幕归一化坐标uBlackHoleScreenPos实现视角自由旋转时引力透镜的完美跟随多普勒红移蓝移模拟Doppler Beaming在吸积盘一侧增强亮度偏向亮蓝朝向观察者高速运动另一侧降低亮度偏向暗红远离观察者还原真实的相对论物理效应单 Pass 极致高能性能全套引力偏折方程仅需两次向量运算与单次纹理重采样在手机端保持恒定60 FPS满帧渲染。用严谨的广义相对论方程在三维 Web 空间雕刻时空弯曲的宇宙奇迹赋予前端界面令人惊叹的硬核极客美学。