Stats 跟随着 three一起安装在 node_modules\three\examples\jsm\libs 下
javascript
const stats = Stats();
// 设置模式,运行时鼠标点击可以自动切换3种模式
stats.setMode(0);
// 放置在浏览器右上角
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
// 放到dom中显示
document.body.appendChild(stats.domElement);
function animate() {
// **别忘了此处的实时更新
stats.update();
renderer.render( scene, camera );
}
renderer.setAnimationLoop( animate );
javascript
// 自定义调试脚本 debug.js
class ThreeJSDebugger {
constructor(scene, camera, renderer) {
this.scene = scene;
this.camera = camera;
this.renderer = renderer;
this.helpers = new Map();
this.initGlobalHelpers();
}
initGlobalHelpers() {
// 将调试器挂载到window,方便控制台调用
window.THREE_DEBUG = {
showAxes: (size = 5) => this.addAxesHelper(size),
showGrid: (size = 10, divisions = 10) => this.addGridHelper(size, divisions),
showCamera: () => this.addCameraHelper(),
showLights: () => this.addLightHelpers(),
showBoundingBoxes: () => this.addBoundingBoxHelpers(),
showStats: () => this.addStatsPanel(),
clearHelpers: () => this.removeAllHelpers(),
logSceneGraph: () => this.logSceneHierarchy(),
getObjectByClick: () => this.setupRaycastDebug(),
toggleWireframe: () => this.toggleWireframeMode()
};
}
addAxesHelper(size) {
const helper = new THREE.AxesHelper(size);
this.scene.add(helper);
this.helpers.set(`axes_${Date.now()}`, helper);
console.log(`已添加坐标轴助手,大小: ${size}`);
}
addGridHelper(size, divisions) {
const helper = new THREE.GridHelper(size, divisions, 0x444444, 0x888888);
this.scene.add(helper);
this.helpers.set(`grid_${Date.now()}`, helper);
}
addCameraHelper() {
const helper = new THREE.CameraHelper(this.camera);
this.scene.add(helper);
this.helpers.set('camera', helper);
}
addLightHelpers() {
this.scene.traverse((object) => {
if (object.isLight) {
let helper;
if (object.isDirectionalLight) {
helper = new THREE.DirectionalLightHelper(object, 1);
} else if (object.isPointLight) {
helper = new THREE.PointLightHelper(object, 1);
} else if (object.isSpotLight) {
helper = new THREE.SpotLightHelper(object);
}
if (helper) {
this.scene.add(helper);
this.helpers.set(`light_${object.uuid}`, helper);
}
}
});
}
logSceneHierarchy() {
console.group('Three.js 场景层级');
this.scene.traverse((obj) => {
const indent = ' '.repeat(obj.parent ? 2 : 0);
console.log(`${indent}${obj.type}: ${obj.name || 'unnamed'} (${obj.uuid})`);
});
console.groupEnd();
}
setupRaycastDebug() {
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const onClick = (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, this.camera);
const intersects = raycaster.intersectObjects(this.scene.children, true);
if (intersects.length > 0) {
const object = intersects[0].object;
console.group('点击对象信息');
console.log('对象:', object);
console.log('世界位置:', object.position);
console.log('材质:', object.material);
console.log('几何体:', object.geometry);
console.groupEnd();
// 高亮显示
this.highlightObject(object);
}
};
window.addEventListener('click', onClick);
console.log('点击调试已启用,点击场景中的对象查看信息');
}
highlightObject(object) {
// 移除之前的高亮
this.scene.traverse((obj) => {
if (obj.userData.isHighlighted) {
obj.material = obj.userData.originalMaterial;
delete obj.userData.isHighlighted;
}
});
// 保存原始材质并应用高亮
object.userData.originalMaterial = object.material;
object.userData.isHighlighted = true;
object.material = new THREE.MeshBasicMaterial({
color: 0xffff00,
wireframe: true
});
// 3秒后恢复
setTimeout(() => {
if (object.userData.isHighlighted) {
object.material = object.userData.originalMaterial;
delete obj.userData.isHighlighted;
}
}, 3000);
}
}
// 使用示例
// 在控制台输入: THREE_DEBUG.showAxes(10)
// 在控制台输入: THREE_DEBUG.logSceneGraph()
javascript
class PerformanceMonitor {
constructor(renderer) {
this.renderer = renderer;
this.metrics = {
fps: 0,
memory: 0,
drawCalls: 0,
triangles: 0,
geometries: 0,
textures: 0
};
this.initStats();
this.initMemoryMonitor();
this.initCustomPanel();
}
initStats() {
// 使用Stats.js
this.stats = new Stats();
this.stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3: custom
document.body.appendChild(this.stats.dom);
// 自定义面板
this.customPanel = new Stats.Panel('THREE', '#ff8', '#221');
this.stats.addPanel(this.customPanel);
}
initMemoryMonitor() {
// 监控WebGL内存使用
if (this.renderer.info) {
setInterval(() => {
const info = this.renderer.info;
this.metrics = {
fps: this.stats.dom.children[0].children[0].innerText,
memory: (performance.memory ? performance.memory.usedJSHeapSize / 1048576 : 0).toFixed(2),
drawCalls: info.render.calls,
triangles: info.render.triangles,
geometries: info.memory.geometries,
textures: info.memory.textures
};
// 更新自定义面板
this.customPanel.update(
this.metrics.drawCalls,
Math.max(this.metrics.drawCalls, 1000)
);
// 输出警告
if (this.metrics.drawCalls > 500) {
console.warn(`Draw Calls过高: ${this.metrics.drawCalls}`);
}
if (this.metrics.triangles > 1000000) {
console.warn(`三角形数量过多: ${this.metrics.triangles}`);
}
}, 1000);
}
}
initCustomPanel() {
// 创建自定义性能显示
this.infoBox = document.createElement('div');
this.infoBox.style.cssText = `
position: fixed;
top: 60px;
left: 0;
background: rgba(0,0,0,0.8);
color: white;
padding: 10px;
font-family: monospace;
font-size: 12px;
z-index: 1000;
max-width: 300px;
`;
document.body.appendChild(this.infoBox);
setInterval(() => this.updateInfoBox(), 500);
}
updateInfoBox() {
const info = this.renderer.info;
const html = `
<div><strong>Three.js 性能监控</strong></div>
<div>Draw Calls: ${info.render.calls}</div>
<div>Triangles: ${info.render.triangles.toLocaleString()}</div>
<div>Points: ${info.render.points}</div>
<div>Lines: ${info.render.lines}</div>
<div>Geometries: ${info.memory.geometries}</div>
<div>Textures: ${info.memory.textures}</div>
<div>Programs: ${info.programs ? info.programs.length : 'N/A'}</div>
${performance.memory ? `
<div>内存使用: ${(performance.memory.usedJSHeapSize / 1048576).toFixed(2)} MB</div>
<div>内存限制: ${(performance.memory.jsHeapSizeLimit / 1048576).toFixed(2)} MB</div>
` : ''}
`;
this.infoBox.innerHTML = html;
}
logPerformance() {
console.table({
'Draw Calls': this.metrics.drawCalls,
'Triangles': this.metrics.triangles.toLocaleString(),
'Geometries': this.metrics.geometries,
'Textures': this.metrics.textures,
'FPS': this.metrics.fps,
'Memory (MB)': this.metrics.memory
});
}
}
// 使用
const perfMonitor = new PerformanceMonitor(renderer);
// 在控制台输入: perfMonitor.logPerformance()