使用粗糙度为 0 的 GLTF Principled BSDF material 导出的立方体在 Three.js 中无法正确显示
Cube exported using GLTF with 0 roughness Principled BSDF material doesn't display properly in Three.js
我的 Blender 材质出现在 three.js 中时遇到问题。我一直在 SO 和其他地方看到提到的一个重要细节是 GLTF 格式对在 Blender 中导出节点设置的支持有限,最好坚持使用 Principled BSDF 等基础知识。然而,即使使用基本的 Principled BSDF 设置(如下图所示),创建粗糙度为 0 的灰色反射立方体,我也看不到 three.js(也如图)中的任何反射率。
这是我的 three.js 场景:
import * as THREE from "three"
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js"
(async () => {
const gScene = new THREE.Scene()
const canvas = document.querySelector("#c")
const gRenderer = new THREE.WebGLRenderer({canvas})
const gCamera = new THREE.PerspectiveCamera(50, canvas.clientWidth/canvas.clientHeight, 0.1, 1000)
gCamera.position.x = 0
gCamera.position.Y = 100
gCamera.position.z = 20
const controls = new OrbitControls(gCamera, canvas)
controls.target.set(0,5,0)
controls.update()
const ambientLight = new THREE.AmbientLight(0xffffff, 40)
gScene.add(ambientLight)
const gltfLoader = new GLTFLoader()
let scene = await new Promise((resolve, reject) => {
gltfLoader.load('./scene.glb', (loadedGLB) => {
resolve(loadedGLB.scene)
})
})
gScene.add(scene)
function resizeRendererToDisplaySize(renderer){
const canvas = renderer.domElement
const pixelRatio = window.devicePixelRatio
const width = canvas.clientWidth * pixelRatio | 0
const height = canvas.clientHeight * pixelRatio | 0
const needResize = canvas.width !== width || canvas.height !== height
if (needResize){
renderer.setSize(width, height, false)
}
return needResize
}
function render(){
if(resizeRendererToDisplaySize(gRenderer)){
let canvas = gRenderer.domElement
gCamera.aspect = canvas.clientWidth/ canvas.clientHeight
gCamera.updateProjectionMatrix()
}
gRenderer.render(gScene,gCamera)
requestAnimationFrame(render)
}
requestAnimationFrame(render)
})()
混合文件:https://drive.google.com/file/d/1rJXmlKuZsNXl3zRt8YqaB7nUamOfKRw3/view?usp=sharing
您可以通过将 HDR 环境贴图添加到您的场景来实现您想要的效果。这个想法是加载相应的纹理,例如通过 RGBELoader
,使用 PMREMGenerator
对其进行预处理,然后将其应用于 Scene.environment
。通过这样做,纹理被设置为场景中所有 PBR 材质的环境贴图。
我建议您查看存储库中的基本 glTF 示例以了解更多详细信息。还要确保使用相同的渲染器配置(意味着确保在 sRGB 颜色 space 下工作并使用色调映射)。
我的 Blender 材质出现在 three.js 中时遇到问题。我一直在 SO 和其他地方看到提到的一个重要细节是 GLTF 格式对在 Blender 中导出节点设置的支持有限,最好坚持使用 Principled BSDF 等基础知识。然而,即使使用基本的 Principled BSDF 设置(如下图所示),创建粗糙度为 0 的灰色反射立方体,我也看不到 three.js(也如图)中的任何反射率。
这是我的 three.js 场景:
import * as THREE from "three"
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js"
(async () => {
const gScene = new THREE.Scene()
const canvas = document.querySelector("#c")
const gRenderer = new THREE.WebGLRenderer({canvas})
const gCamera = new THREE.PerspectiveCamera(50, canvas.clientWidth/canvas.clientHeight, 0.1, 1000)
gCamera.position.x = 0
gCamera.position.Y = 100
gCamera.position.z = 20
const controls = new OrbitControls(gCamera, canvas)
controls.target.set(0,5,0)
controls.update()
const ambientLight = new THREE.AmbientLight(0xffffff, 40)
gScene.add(ambientLight)
const gltfLoader = new GLTFLoader()
let scene = await new Promise((resolve, reject) => {
gltfLoader.load('./scene.glb', (loadedGLB) => {
resolve(loadedGLB.scene)
})
})
gScene.add(scene)
function resizeRendererToDisplaySize(renderer){
const canvas = renderer.domElement
const pixelRatio = window.devicePixelRatio
const width = canvas.clientWidth * pixelRatio | 0
const height = canvas.clientHeight * pixelRatio | 0
const needResize = canvas.width !== width || canvas.height !== height
if (needResize){
renderer.setSize(width, height, false)
}
return needResize
}
function render(){
if(resizeRendererToDisplaySize(gRenderer)){
let canvas = gRenderer.domElement
gCamera.aspect = canvas.clientWidth/ canvas.clientHeight
gCamera.updateProjectionMatrix()
}
gRenderer.render(gScene,gCamera)
requestAnimationFrame(render)
}
requestAnimationFrame(render)
})()
混合文件:https://drive.google.com/file/d/1rJXmlKuZsNXl3zRt8YqaB7nUamOfKRw3/view?usp=sharing
您可以通过将 HDR 环境贴图添加到您的场景来实现您想要的效果。这个想法是加载相应的纹理,例如通过 RGBELoader
,使用 PMREMGenerator
对其进行预处理,然后将其应用于 Scene.environment
。通过这样做,纹理被设置为场景中所有 PBR 材质的环境贴图。
我建议您查看存储库中的基本 glTF 示例以了解更多详细信息。还要确保使用相同的渲染器配置(意味着确保在 sRGB 颜色 space 下工作并使用色调映射)。