Hello, I have used this method.
But the effect is not ideal.
This is a comparison chart.
As you can see Using HDR_JPG to apply background, the image displays jagged.
But using HDR is relatively smooth.
My steps are:
- Download a 4K HDR file (sunflowers_puresky_4k. hdr)
- Use tools to convert it to HDR_JPG (sunflowers_puresky_4k. jpg)
- Refer to the official code of gainmap js
This is my code:
<template>
<div>
</div>
</template>
<script>
import * as THREE from 'three';
import {GUI} from 'three/examples/jsm/libs/lil-gui.module.min.js';
import Stats from 'three/examples/jsm/libs/stats.module.js';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader.js';
import {GainMapLoader, HDRJPGLoader} from '@monogrid/gainmap-js';
const params = {
envMap: 'HDR JPG',
roughness: 0.0,
metalness: 1.0,
exposure: 1.0
};
let container, stats;
let camera, scene, renderer, controls;
let torusMesh;
let hdrJpg, hdrJpgPMREMRenderTarget, hdrJpgEquirectangularMap;
let gainMap, gainMapPMREMRenderTarget, gainMapBackground;
let hdrPMREMRenderTarget, hdrEquirectangularMap;
export default {
mounted() {
this.init();
this.animate();
// 监听窗口变化
window.addEventListener("resize", () => {
// 重置渲染器宽高比
renderer.setSize(window.innerWidth, window.innerHeight);
// 重置相机宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 更新相机投影矩阵
camera.updateProjectionMatrix();
});
},
methods: {
animate() {
requestAnimationFrame(this.animate);
stats.begin();
this.render();
stats.end();
},
render() {
let pmremRenderTarget, equirectangularMap;
switch (params.envMap) {
case 'HDR JPG':
pmremRenderTarget = hdrJpgPMREMRenderTarget;
equirectangularMap = hdrJpgEquirectangularMap;
break;
case 'Webp Gain map (separate)':
pmremRenderTarget = gainMapPMREMRenderTarget;
equirectangularMap = gainMapBackground;
break;
case 'HDR':
pmremRenderTarget = hdrPMREMRenderTarget;
equirectangularMap = hdrEquirectangularMap;
break;
}
torusMesh.material.roughness = params.roughness;
torusMesh.material.metalness = params.metalness;
scene.environment = equirectangularMap;
scene.background = equirectangularMap;
renderer.toneMappingExposure = params.exposure;
renderer.render(scene, camera);
},
init() {
//
container = document.createElement('div');
document.body.appendChild(container);
//
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, -120);
//
scene = new THREE.Scene();
//
renderer = new THREE.WebGLRenderer();
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
// let geometry = new THREE.TorusKnotGeometry(18, 8, 200, 40, 1, 3);
let geometry = new THREE.BoxGeometry(10, 10, 10);
let material = new THREE.MeshStandardMaterial({
color: 0xffffff,
metalness: params.metalness,
roughness: params.roughness
});
torusMesh = new THREE.Mesh(geometry, material);
scene.add(torusMesh);
geometry = new THREE.PlaneGeometry(200, 200);
material = new THREE.MeshBasicMaterial();
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
THREE.DefaultLoadingManager.onLoad = function () {
pmremGenerator.dispose();
};
hdrJpg = new HDRJPGLoader(renderer)
.load('textures/sunflowers_puresky_4k.jpg', function () {
hdrJpgEquirectangularMap = hdrJpg.renderTarget.texture;
hdrJpgPMREMRenderTarget = pmremGenerator.fromEquirectangular(hdrJpgEquirectangularMap);
hdrJpgEquirectangularMap.mapping = THREE.EquirectangularReflectionMapping;
hdrJpgEquirectangularMap.needsUpdate = true;
hdrJpg.dispose();
}, function (progress) {
console.log('jpg', progress);
});
gainMap = new GainMapLoader(renderer)
.load([
'textures/gainmap/spruit_sunrise_4k.webp',
'textures/gainmap/spruit_sunrise_4k-gainmap.webp',
'textures/gainmap/spruit_sunrise_4k.json'
], function () {
gainMapBackground = hdrJpg.renderTarget.texture;
gainMapPMREMRenderTarget = pmremGenerator.fromEquirectangular(gainMapBackground);
gainMapBackground.mapping = THREE.EquirectangularReflectionMapping;
gainMapBackground.needsUpdate = true;
gainMap.dispose();
}, function (progress) {
});
hdrEquirectangularMap = new RGBELoader()
.load('textures/sunflowers_puresky_4k.hdr', function () {
hdrPMREMRenderTarget = pmremGenerator.fromEquirectangular(hdrEquirectangularMap);
hdrEquirectangularMap.mapping = THREE.EquirectangularReflectionMapping;
hdrEquirectangularMap.minFilter = THREE.LinearFilter;
hdrEquirectangularMap.magFilter = THREE.LinearFilter;
hdrEquirectangularMap.needsUpdate = true;
}, function (progress) {
});
//
controls = new OrbitControls(camera, renderer.domElement);
controls.minDistance = 50;
controls.maxDistance = 300;
//
stats = new Stats();
container.appendChild(stats.dom);
//
const gui = new GUI();
gui.add(params, 'envMap', ['HDR JPG', 'Webp Gain map (separate)', 'HDR']).onChange();
gui.add(params, 'roughness', 0, 1, 0.01);
gui.add(params, 'metalness', 0, 1, 0.01);
gui.add(params, 'exposure', 0, 2, 0.01);
gui.open();
},
},
};
</script>
Excuse me, is there an error in any step?