threejs渲染hdr环境贴图实例

threejs yekong

最近在学习threejs渲染时,发现threejs可以渲染hdr文件,之前不清楚hdr这种文件是做什么的,于是查询了一番,原来是环境贴图。于是也学一下threejs如何渲染环境贴图。

效果截图

threejs渲染hdr环境贴图实例

渲染动画

引入依赖

// threejs
import * as THREE from "three";
//轨道控制器
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
// hdr加载器
import {RGBELoader} from "three/examples/jsm/loaders/RGBELoader";
// 连接判断,用来控制请求地址
import {link} from "@/config/config.js";

创建场景

const scene = new THREE.Scene();

获取div宽高

并不是所有threejs项目都是全屏项目,所以我们在渲染前先创建一个div,让这个div跟随父div大小变化,这样就可以快速将项目移植到对应的项目中了。

that.width = that.$refs.canvasGLTF.offsetWidth
that.height = that.$refs.canvasGLTF.offsetHeight

创建相机

const camera = that.camera = new THREE.PerspectiveCamera(
  75,
  that.width / that.height,
  0.1,
  1000
);
camera.aspect = that.width / that.height;
//   更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 设置相机位置
camera.position.set(0, 0, 20);
scene.add(camera);

初始化渲染器

const renderer = that.renderer = new THREE.WebGLRenderer({
    logarithmicDepthBuffer: true,
    antialias: true,
});

// 设置渲染的尺寸大小
renderer.setSize(that.width, that.height);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;
renderer.physicallyCorrectLights = true;
renderer.setClearColor(0xcccccc, 1);
renderer.autoClear = false;
// 设置电影渲染模式
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.sortObjects = true;
renderer.logarithmicDepthBuffer = true;
renderer.setPixelRatio(window.devicePixelRatio);

创建轨道控制器

const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;

添加坐标轴辅助器

// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

刷新帧

function render() {
    controls.update();
    renderer.render(scene, camera);
    //   渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render);
}

render();

添加hdr环境渲染

这里我们通过RGBELoader来加载hdr环境贴图,并通过EquirectangularReflectionMapping来设置材质的反射映射,

// 添加hdr环境纹理
const loader = new RGBELoader();
loader.load(link + "demo.hdr", function (texture) {
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.background = texture;
    scene.environment = texture;
});

显示加载进度

当资源过大时,加载文件时,一直处在黑屏状态很不友好,所以我们显示一个进度加载状态,来给用户一个实时反馈,这里我们使用loading,RGBELoader环境贴图加载器中的manager可以实现我们想要的效果。
我们在加载资源的时候增加一个方法:handleProgress用来处理资源加载回调。

资源加载

loader.load(link + "demo.hdr", function (texture) {
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.background = texture;
    scene.environment = texture;
});

加载方法回调

function handleProgress(progressEvent) {
    console.log('handleProgress', progressEvent.loaded, progressEvent.total)
    var div = document.getElementById('LoadingInfo')
    div.style.display = 'flex'
    div.innerText = `加载模型中:${(progressEvent.loaded / progressEvent.total * 100).toFixed(0)}%`
    if ((progressEvent.loaded / progressEvent.total * 100).toFixed(0) >= 100) {
        div.style.display = 'none'
    }
}

加载zip文件

three项目的资源一般文件都很大,小的几兆,大的几百兆,文件太大的话,对带宽要求会很高会拖慢加载进度,一般会对素材进行压缩处理,这里我们对环境贴图资源进行zip压缩,通过axios请求数据,解压后,再通过RGBELoader加载器加载环境贴图。

环境贴图资源zip压缩前是13.7M,zip压缩后是10.8M,压缩了2.9M.

加载zip文件

压缩完成后,接下来我们来写请求资源的方法,使用axios去请求我们的zip资源,并通过onDownloadProgress来获取下载进度

   // 获取zip资源
    async getZipData() {
      var that = this;
      try {
        const response = await axios.get(link + "demo.zip", {
          responseType: 'arraybuffer',
          onDownloadProgress: (progressEvent) => {
            let percentCompleted = Math.round(progressEvent.loaded * 100 / progressEvent.total)
            var div = document.getElementById('LoadingInfo')
            div.style.display = 'flex'
            div.innerText = `下载资源中: ${percentCompleted}%`
          }
        });

        let files = new window.File([response.data], 'zipFile', {type: 'zip'});
        var new_zip = new JSZip();

        // 解压缩文件对象
        const result = await new_zip.loadAsync(files);

        // 压缩包的模型文件列表
        let fileList = result.files;
        for (let key in fileList) {
          // 读取模型文件内容
          const content = await new_zip.file(key).async('arraybuffer');

          // Blob构造文件地址,通过url加载模型
          let blob = new Blob([content]);
          let modelUrls = URL.createObjectURL(blob);
          // 处理每个模型文件地址
          return new Promise((resolve, reject) => {
            resolve(modelUrls);
          });
        }

      } catch (error) {
        console.error("Error fetching data:", error);
      }
    },

然后我们再通过RGBELoader来加载我们的资源。

const loader = new RGBELoader();
// 下载zip资源
var modelUrls = await that.getZipData()

loader.load(modelUrls, function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = texture;
scene.environment = texture;
}, that.handleProgress);

完整实例代码下载

项目运行环境 vue3 vite js nodejs 14

相关文件下载地址
此资源需支付 ¥5 后下载
支付宝购买扫右侧红包码购买更优惠,如无法下载请联系微信:17331886870
喜欢
threejs渲染hdr环境贴图实例