为什么 Three.js 等距柱状背景 colors/contrast 如此糟糕,我该如何解决?
Why are Three.js equirectangular backgrounds's colors/contrast so bad and how can I fix them?
我在一家建筑公司的网站项目中使用 Three.js。他们想要一些我使用 phone(Google 像素 5)制作的 360° 照片(光球)。他们还想展示他们的一个项目的 3D 表示,因此使用 Three.js 似乎是最好的解决方案。
这是 Google 照片中的样子:
Google Photos screenshot
以及它在 Three.js 中的样子:
Three.js screenshot
你可以看到与原始版本相比,颜色真的很糟糕(对比度、白平衡、idk)。
这是我第一次使用 Three.js 所以这是我的代码:
场景:
async connectedCallback() {
// Scene
this.scene = new THREE.Scene();
// Background equirectangular texture
const background_img = this.getAttribute('background');
if (background_img) this.loadBackground(background_img);
// Camera
this.camera = new THREE.PerspectiveCamera(60, this.clientWidth / this.clientHeight, 1, 5000);
// Lights
// this.scene.add(new THREE.HemisphereLight(0xffeeb1, 0x080820, 0));
const spotLight = new THREE.SpotLight(0xffa95c, 5);
spotLight.position.set(20, 20, 20);
spotLight.castShadow = true;
spotLight.shadow.bias = -0.0001;
spotLight.shadow.mapSize.width = 1024 * 4;
spotLight.shadow.mapSize.height = 1024 * 4;
this.scene.add(spotLight);
// Renderer
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.toneMapping = THREE.ReinhardToneMapping;
this.renderer.toneMappingExposure = 2.3;
this.renderer.shadowMap.enabled = true;
this.renderer.setPixelRatio(devicePixelRatio);
this.renderer.setSize(this.clientWidth, this.clientHeight);
this.appendChild(this.renderer.domElement);
// Orbit controls
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.autoRotate = true;
// Resize event
addEventListener('resize', e => this.resize());
// Load model
const url = this.getAttribute('model');
if (url) this.loadModel(url);
// Animate
this.resize();
this.animate();
// Resize again in .1s
setTimeout(() => this.resize(), 100);
// Init observer
new IntersectionObserver(entries => this.classList.toggle('visible', entries[0].isIntersecting), { threshold: 0.1 }).observe(this);
}
背景(光球):
loadBackground(src) {
const equirectangular = new THREE.TextureLoader().load(src);
equirectangular.mapping = THREE.EquirectangularReflectionMapping;
// Things Github Copilot suggested, removing it does not change colors so I thing it's not the problem
equirectangular.magFilter = THREE.LinearFilter;
equirectangular.minFilter = THREE.LinearMipMapLinearFilter;
equirectangular.format = THREE.RGBFormat;
equirectangular.encoding = THREE.sRGBEncoding;
equirectangular.anisotropy = 16;
this.scene.background = equirectangular;
}
正如 Marquizzo 在评论中所说:
You’re changing the renderer’s tone mapping and the exposure. It’s normal for the results to be different when you make modifications to the color output.
我一直说问题不在于 Github Copilot 建议的那几行,因为我在删除这些行时得到了相同的结果,但我尝试一次删除一行,结果证明这一行是问题所在:
equirectangular.format = THREE.RGBFormat;
现在我的结果与 Google 照片的结果相比有点暗,但颜色终于准确了!我还有很多东西要学哈哈
Three.js screenshot after removing the problematic line
谢谢马奎佐!
我在一家建筑公司的网站项目中使用 Three.js。他们想要一些我使用 phone(Google 像素 5)制作的 360° 照片(光球)。他们还想展示他们的一个项目的 3D 表示,因此使用 Three.js 似乎是最好的解决方案。
这是 Google 照片中的样子:
Google Photos screenshot
以及它在 Three.js 中的样子:
Three.js screenshot
你可以看到与原始版本相比,颜色真的很糟糕(对比度、白平衡、idk)。
这是我第一次使用 Three.js 所以这是我的代码:
场景:
async connectedCallback() {
// Scene
this.scene = new THREE.Scene();
// Background equirectangular texture
const background_img = this.getAttribute('background');
if (background_img) this.loadBackground(background_img);
// Camera
this.camera = new THREE.PerspectiveCamera(60, this.clientWidth / this.clientHeight, 1, 5000);
// Lights
// this.scene.add(new THREE.HemisphereLight(0xffeeb1, 0x080820, 0));
const spotLight = new THREE.SpotLight(0xffa95c, 5);
spotLight.position.set(20, 20, 20);
spotLight.castShadow = true;
spotLight.shadow.bias = -0.0001;
spotLight.shadow.mapSize.width = 1024 * 4;
spotLight.shadow.mapSize.height = 1024 * 4;
this.scene.add(spotLight);
// Renderer
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.toneMapping = THREE.ReinhardToneMapping;
this.renderer.toneMappingExposure = 2.3;
this.renderer.shadowMap.enabled = true;
this.renderer.setPixelRatio(devicePixelRatio);
this.renderer.setSize(this.clientWidth, this.clientHeight);
this.appendChild(this.renderer.domElement);
// Orbit controls
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.autoRotate = true;
// Resize event
addEventListener('resize', e => this.resize());
// Load model
const url = this.getAttribute('model');
if (url) this.loadModel(url);
// Animate
this.resize();
this.animate();
// Resize again in .1s
setTimeout(() => this.resize(), 100);
// Init observer
new IntersectionObserver(entries => this.classList.toggle('visible', entries[0].isIntersecting), { threshold: 0.1 }).observe(this);
}
背景(光球):
loadBackground(src) {
const equirectangular = new THREE.TextureLoader().load(src);
equirectangular.mapping = THREE.EquirectangularReflectionMapping;
// Things Github Copilot suggested, removing it does not change colors so I thing it's not the problem
equirectangular.magFilter = THREE.LinearFilter;
equirectangular.minFilter = THREE.LinearMipMapLinearFilter;
equirectangular.format = THREE.RGBFormat;
equirectangular.encoding = THREE.sRGBEncoding;
equirectangular.anisotropy = 16;
this.scene.background = equirectangular;
}
正如 Marquizzo 在评论中所说:
You’re changing the renderer’s tone mapping and the exposure. It’s normal for the results to be different when you make modifications to the color output.
我一直说问题不在于 Github Copilot 建议的那几行,因为我在删除这些行时得到了相同的结果,但我尝试一次删除一行,结果证明这一行是问题所在:
equirectangular.format = THREE.RGBFormat;
现在我的结果与 Google 照片的结果相比有点暗,但颜色终于准确了!我还有很多东西要学哈哈
Three.js screenshot after removing the problematic line
谢谢马奎佐!