Addressing Discrepancies Between three.js GLTF Model Rendering and GLTFViewer Website Previews: Causes – Lighting and Environment Maps
function init(e) { //声明初始化函数
$("#preview3D").html(""); //获取容器dom对象
let camera, renderer, controls, guiControls, domW, domH, animateId; //声明变量
domW = $("#preview3D").css("width").replace("px", "") * 1; //拿宽高
domH = $("#preview3D").css("height").replace("px", "") * 1;
// 实例化renderer
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
// 背景色
renderer.setClearColor(0x666666, 0);
// 屏幕物理像素和px比率
renderer.setPixelRatio(window.devicePixelRatio);
// three.js 的色彩空间渲染方式 【重要】
renderer.outputEncoding = THREE.sRGBEncoding;
// 这个不知道干嘛用的 反正我加上了
renderer.textureEncoding = THREE.sRGBEncoding;
// 设置canvas宽高
renderer.setSize(domW, domH);
// 开启渲染阴影
renderer.shadowMap.enabled = true;
renderer.hadowMapEnabled = true;
// 将renderer 加到dom元素上
$("#preview3D")[0].appendChild(renderer.domElement);
// 实例化场景
scene = new THREE.Scene();
// 添加灯光 【重要】
function addLights(level) {
scene.add(new THREE.AmbientLight(0xffffff, 0.3));
var light = new THREE.DirectionalLight(0xffffff, 0.8 * Math.PI);
light.position.set(0, 50, 0);
scene.add(light);
}
addLights();
// 灯光参数我是按照gltfViewer中的参数输入的,为了保持一直可以根据需求动态添加
/*添加背景 */
createObjDetailScene();
// 添加背景声明函数
function createObjDetailScene() {
// 实例化透视投影镜头
camera = new THREE.PerspectiveCamera(45, domW / domH, 1, 1000);
camera.position.set(0, 0, -1);
camera.lookAt(scene.position);
// 注意参数
initContent();
/* 场景中的内容 */
function initContent() {
let object;
// 加载 glTF 格式的模型,实例化gltfLoader加载器
let loader = new THREE.GLTFLoader(); /*实例化加载器*/
var pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
let flag = false;
// 这里应该是根据需要走判断 本身发暗的模型就用sunset
// 发亮急用court
// 不需要环境的使用null
let str = "img/venice_sunset_1k.hdr";
// str = "img/footprint_court_2k.hdr";
console.log(str);
try {
// 单张环境贴图加载器实例化
new THREE.RGBELoader()
.setDataType(THREE.UnsignedByteType)
.load(str, function (texture) {
var envMap = pmremGenerator.fromEquirectangular(texture)
.texture;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
});
} catch (e) {
console.log(e);
}
// 加载gltf模型
loader.load(url, function (gltf) {
console.log(gltf)
gltf.scene.traverse(function (child) {
if (child instanceof THREE.Mesh) {
//设置模型生成阴影并接收阴影
child.castShadow = true;
child.receiveShadow = true;
}
});
object = gltf.scene
object.scale.set(100, 100, 100);
let center = getCenterPosition(object);
object.position.set(-center.x, -center.y, -center.z);
scene.add(gltf.scene);
},xhr=>{
console.log(xhr)
},err=>{
console.log(err)
});
}
// 控制器 放大倍数 缩小倍数 是否自动旋转及速度
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minDistance = 200;
controls.maxDistance = 800;
controls.autoRotate = true;
controls.autoRotateSpeed = 1.7;
animate();
// 根据屏幕大小变化自动放大缩小canvas
window.addEventListener("resize", onWindowResize, false);
function onWindowResize(event) {
SCREEN_WIDTH = $("#preview3D").css("width").replace("px", "") * 1;
SCREEN_HEIGHT = $("#preview3D").css("height").replace("px", "") * 1;
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
if (camera) {
camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
camera.updateProjectionMatrix();
}
}
function animate() {
animateId = requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
}
const getCenterPosition = (object) => {
let p;
if (object.isMesh) {
object.geometry.computeBoundingBox();
p = object.geometry.boundingBox.getCenter(new THREE.Vector3()); //.multiplyScalar(1) //加上这个表示放大了几倍 1为放大倍数
} else {
p = new THREE.Box3()
.setFromObject(object)
.getCenter(new THREE.Vector3());
}
return p;
};
};