Skip to content

67. HDR:亮度范围更广的全景图

Published:

前面我们设置过好几次天空盒背景了。

我们是从网上找了一些全景图:

image.png

用工具分割成前后左右上下 6 张图片:

image.png

image.png

image.png

然后用 CubeTextureLoader 加载并在代码里使用的:

image.png

但其实设置全景图还有另一种方式,就是 HDR 文件。

image.png

它比 png、jpg 能存储更大的亮度范围,很适合用来做全景图。

比如把 threejs 官方仓库的这个 hdr 文件下载下来:

https://github.com/mrdoob/three.js/blob/b2e0b0ce5cd1aee526a93c60b08ea5510e33eda0/examples/textures/equirectangular/san_giuseppe_bridge_2k.hdr

image.png

image.png

这明显也是一张全景图:

image.png

如何加载 hdr 文件作为全景图呢?

这就需要用到 RGBELoader 了。

我们来写下代码:

npx create-vite hdr-background

image.png

进入项目,安装依赖:

npm install
npm install --save three
npm install --save-dev @types/three

改下 src/main.js

import './style.css';
import * as THREE from 'three';
import {
    OrbitControls
} from 'three/addons/controls/OrbitControls.js';
import mesh from './mesh.js';

const scene = new THREE.Scene();
scene.add(mesh);

const directionLight = new THREE.DirectionalLight(0xffffff);
directionLight.position.set(500, 400, 300);
scene.add(directionLight);

const ambientLight = new THREE.AmbientLight();
scene.add(ambientLight);

const width = window.innerWidth;
const height = window.innerHeight;

const helper = new THREE.AxesHelper(500);
scene.add(helper);

const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 10000);
camera.position.set(300, 700, 300);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(width, height)

function render(time) {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

render();

document.body.append(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);

window.onresize = function () {
  const width = window.innerWidth;
  const height = window.innerHeight;

  renderer.setSize(width,height);

  camera.aspect = width / height;
  camera.updateProjectionMatrix();
};

创建 Scene、Light、Camera、Renderer。

改下 style.css

body {
  margin: 0;
}

先跑下:

npm run dev

image.png

image.png

然后我们加载下 hdr 文件:

把刚才的 pbr 文件复制到 public 目录下:

image.png

代码里加载下:

image.png

const rgbeloader = new RGBELoader();

rgbeloader.load('./pic.hdr', function ( texture ) {
  texture.mapping = THREE.EquirectangularReflectionMapping;
  scene.background = texture;
});

2025-04-18 22.45.55.gif

可以看到,现在的光线非常真实,相比之前用 CubeTextureLoader 加载 6 张图作为。

这就是 hdr 文件的好处。

这个 mapping 是指定如何解析这张图片的:

image.png

不指定就是这样:

image.png

其实之前的全景图也不是非得切割成天空盒的六张图再用,比如这张图片:

pic.jpg

image.png

如果不切割成 6 张图,也可以直接用:

image.png

const textureLoader = new THREE.TextureLoader();

textureLoader.load('./pic.jpg', function ( texture ) {
  texture.mapping = THREE.EquirectangularReflectionMapping;
  scene.background = texture;
});

2025-04-18 22.54.35.gif

jpg 文件是没有 hdr 文件存储的亮度信息多的,全景图还是用 hdr 比较好。

案例代码上传了小册仓库

总结

这节我们学了用 .hdr 文件作为全景图。

hdr 文件能够存储范围更广的亮度信息,作为全景图更加真实。

用 RGBELoader 加载之后,设置 mapping 为 EquirectangularReflectionMapping,然后作为 scene.background 就可以了。

当然,普通的 jpg 文件也不用分割成 6 张图后再用 CubeTextureLoader 加载,也可以用这种方式运行时分割。

后面做全景图的时候,尽量用 hdr 文件,会更加真实。

评论