天空盒
六个渐变面拼成立方体背景,与球体穹顶、纯色背景一键切换,观察地平线的一致性。
说明
背景由六张画布组成,全部用 Canvas 2D 画出垂直渐变:
天顶深蓝、地平线浅蓝、天底接近地面色。其中 +X 面额外画了一个径向光晕,
用来说明天空盒的方向是可以单独控制的。
切到球体穹顶时改用一张竖向渐变纹理贴在大球内壁, 大球半径 420,比场景最远的楼还大,且关闭雾效与深度写入。 纯色背景则用来确认地物本身的对比度。
| 设置 | 数值 | 说明 |
|---|---|---|
| 立方体贴图 | 6 张 256 × 256 画布 | 顺序为 +X、−X、+Y、−Y、+Z、−Z |
| 穹顶球 | 半径 420 | 32 × 24 分段,BackSide |
| 穹顶材质 | Basic,depthWrite: false | 不参与光照与深度排序 |
| 雾 | 0x7fa6c8,110 – 320 | 取地平线的浅蓝,远处楼体自然融入 |
| 场景 | 半径 300 的地面与 160 栋楼 | 楼高 4 – 42,颜色单一 |
| 相机远裁剪 | 900 | 必须大于穹顶半径,否则穹顶被裁掉 |
六面顺序与接缝
const faces = [
skyCanvas(ZENITH, NADIR, true), // +X
skyCanvas(ZENITH, NADIR, false), // -X
skyCanvas(ZENITH, HORIZON, false), // +Y
skyCanvas(HORIZON, NADIR, false), // -Y
skyCanvas(ZENITH, NADIR, false), // +Z
skyCanvas(ZENITH, NADIR, false) // -Z
];
const cubeTexture = new THREE.CubeTexture(faces);
cubeTexture.colorSpace = THREE.SRGBColorSpace;
cubeTexture.needsUpdate = true;
scene.background = cubeTexture;
顺序写错时天与地会对调,表现为地平线出现在画面顶部。
六张图尺寸必须一致,且 needsUpdate 不能漏,
否则纹理不会上传,背景保持黑色。
接缝是否明显取决于相邻面边缘像素是否连续。 用同一组渐变色阶、让每个面的左右边缘颜色一致,接缝基本看不出来; 若某个面单独画了太阳光晕,光晕跨越面边界时就会有断痕, 需要把相邻面的对应位置也补上。
穹顶方案
球体贴图只有一个 UV 方向,实现简单,也没有接缝问题, 但天顶处的纹理会被挤压到极点,细节集中在赤道附近。 它适合纯渐变的天空,不适合带云层细节的实拍图。
side: BackSide 让相机看到球的内壁,
depthWrite: false 避免它挡住之后的物体,
两者缺一都会出现黑屏或遮挡异常。球形背景不受相机位置影响,
但会随相机旋转,这正是需要「天空无限远」的效果。
雾与地平线
雾色与地平线颜色不一致时,远处会先变成灰色再撞上天空, 出现一条明显的硬边。示例把雾色设为地平线的浅蓝, 楼群在远处自然过渡,背景与地面之间没有突兀的分界。
天空盒只是背景。它不参与光照计算,也不会被物体遮挡。
想让天空照亮场景,需要另配环境贴图或 HemisphereLight,
three.js 不会因为设置了背景就自动提供环境光。
背景不是底图。three.js 是三维渲染库,不提供地图瓦片、注记与投影, 天空盒只是画在场景后方的六张图片。