news 2026/7/16 13:28:54

Three.js 第一人称房屋教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Three.js 第一人称房屋教程

第一人称房屋 ·House Scene· ▶ 在线运行案例

  • 案例合集:三维可视化功能案例(threehub.cn)
  • 开源仓库github地址:https://github.com/z2586300277/three-cesium-examples
  • 400个案例代码:网盘链接

你将学到什么

  • FBXLoader 加载 FBX 城市/角色模型
  • 场景雾效增强纵深
  • requestAnimationFrame渲染循环与resize自适应

效果说明

本案例演示第一人称房屋效果:基于 WebGL 实现「第一人称房屋」可视化效果,附完整可运行源码;核心用到 FBXLoader、场景雾效增强纵深。建议先打开文首在线案例查看动态画面,再对照下方源码逐步理解。

核心概念

  • Loader异步加载模型;glTF 返回gltf.scene,加载后注意scale与坐标系。Draco 需配置DRACOLoader

实现步骤

  • 搭建 Scene / Camera / Renderer 与 OrbitControls
  • Loader 异步加载模型/纹理资源
  • rAF 循环中 update 并 render
  • 代码要点

    import * as THREE from 'three';

    import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'; import { FirstPersonControls } from 'three/examples/jsm/controls/FirstPersonControls.js';

    const host = FILE_HOST + 'examples/flowerAndHouse';

    const box = document.getElementById('box');

    const width = box.clientWidth; const height = box.clientHeight; const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 1000);

    const scene = new THREE.Scene();

    const house = new THREE.Group();

    const renderer = new THREE.WebGLRenderer();

    function create() { renderer.setSize(width, height); //设置背景颜色 renderer.setClearColor(0xcce0ff, 1); box.appendChild(renderer.domElement);

    camera.position.set(-500, 60, 0) camera.lookAt(scene.position);

    const light = new THREE.AmbientLight(0xCCCCCC); scene.add(light);

    const axisHelper = new THREE.AxesHelper(1000); scene.add(axisHelper);

    createGrass(); createHouse();

    function createHouse() { createFloor(); const sideWall = createSideWall(); const sideWall2 = createSideWall(); sideWall2.position.z = 300;

    createFrontWall(); createBackWall();

    const roof = createRoof(); const roof2 = createRoof(); roof2.rotation.x = Math.PI / 2; roof2.rotation.y = Math.PI / 4 * 0.6; roof2.position.y = 130; roof2.position.x = -50; roof2.position.z = 155;

    createWindow(); createDoor();

    createBed(); } scene.add(house);

    scene.fog = new THREE.Fog(0xffffff, 10, 1500); }

    function createGrass() { const geometry = new THREE.PlaneGeometry( 10000, 10000);

    const texture = new THREE.TextureLoader().load(host+'/img/grass.jpg'); texture.wrapS = THREE.RepeatWrapping; texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 100, 100 );

    const grassMaterial = new THREE.MeshBasicMaterial({map: texture});

    const grass = new THREE.Mesh( geometry, grassMaterial );

    grass.rotation.x = -0.5 * Math.PI;

    scene.add( grass ); }

    function createFloor() { const geometry = new THREE.PlaneGeometry( 200, 300);

    const texture = new THREE.TextureLoader().load(host + '/img/wood.jpg'); texture.wrapS = THREE.RepeatWrapping; texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 2, 2 );

    const material = new THREE.MeshBasicMaterial({map: texture});

    const floor = new THREE.Mesh( geometry, material );

    floor.rotation.x = -0.5 * Math.PI; floor.position.y = 1; floor.position.z = 150;

    house.add(floor); }

    function createSideWall() { const shape = new THREE.Shape(); shape.moveTo(-100, 0); shape.lineTo(100, 0); shape.lineTo(100,100); shape.lineTo(0,150); shape.lineTo(-100,100); shape.lineTo(-100,0);

    const extrudeGeometry = new THREE.ExtrudeGeometry( shape );

    const texture = new THREE.TextureLoader().load(host+'/img/wall.jpg'); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 0.01, 0.005 );

    var material = new THREE.MeshBasicMaterial( {map: texture} );

    const sideWall = new THREE.Mesh( extrudeGeometry, material ) ;

    house.add(sideWall);

    return sideWall; }

    function createFrontWall() { const shape = new THREE.Shape(); shape.moveTo(-150, 0); shape.lineTo(150, 0); shape.lineTo(150,100); shape.lineTo(-150,100); shape.lineTo(-150,0);

    const window = new THREE.Path(); window.moveTo(30,30) window.lineTo(80, 30) window.lineTo(80, 80) window.lineTo(30, 80); window.lineTo(30, 30); shape.holes.push(window);

    const door = new THREE.Path(); door.moveTo(-30, 0) door.lineTo(-30, 80) door.lineTo(-80, 80) door.lineTo(-80, 0); door.lineTo(-30, 0); shape.holes.push(door);

    const extrudeGeometry = new THREE.ExtrudeGeometry( shape )

    const texture = new THREE.TextureLoader().load(host+'/img/wall.jpg'); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 0.01, 0.005 );

    const material = new THREE.MeshBasicMaterial({map: texture} );

    const frontWall = new THREE.Mesh( extrudeGeometry, material ) ;

    frontWall.position.z = 150; frontWall.position.x = 100; frontWall.rotation.y = Math.PI * 0.5;

    house.add(frontWall); }

    function createBackWall() { const shape = new THREE.Shape(); shape.moveTo(-150, 0) shape.lineTo(150, 0) shape.lineTo(150,100) shape.lineTo(-150,100);

    const extrudeGeometry = new THREE.ExtrudeGeometry( shape )

    const texture = new THREE.TextureLoader().load(host+'/img/wall.jpg'); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 0.01, 0.005 );

    const material = new THREE.MeshBasicMaterial({map: texture});

    const backWall = new THREE.Mesh( extrudeGeometry, material) ;

    backWall.position.z = 150; backWall.position.x = -100; backWall.rotation.y = Math.PI * 0.5;

    house.add(backWall); }

    function createRoof() { const geometry = new THREE.BoxGeometry( 120, 320, 10 );

    const texture = new THREE.TextureLoader().load(host+'/img/tile.jpg'); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 5, 1); texture.rotation = Math.PI / 2; const textureMaterial = new THREE.MeshBasicMaterial({ map: texture});

    const colorMaterial = new THREE.MeshBasicMaterial({ color: 'grey' });

    const materials = [ colorMaterial, colorMaterial, colorMaterial, colorMaterial, colorMaterial, textureMaterial ];

    const roof = new THREE.Mesh( geometry, materials );

    house.add(roof);

    roof.rotation.x = Math.PI / 2; roof.rotation.y = - Math.PI / 4 * 0.6; roof.position.y = 130; roof.position.x = 50; roof.position.z = 155; return roof; }

    function createWindow() { const shape = new THREE.Shape(); shape.moveTo(0, 0); shape.lineTo(0, 50) shape.lineTo(50,50) shape.lineTo(50,0); shape.lineTo(0, 0);

    const hole = new THREE.Path(); hole.moveTo(5,5) hole.lineTo(5, 45) hole.lineTo(45, 45) hole.lineTo(45, 5); hole.lineTo(5, 5); shape.holes.push(hole);

    const extrudeGeometry = new THREE.ExtrudeGeometry(shape);

    var extrudeMaterial = new THREE.MeshBasicMaterial({ color: 'silver' });

    var mesh = new THREE.Mesh( extrudeGeometry, extrudeMaterial ) ; mesh.rotation.y = Math.PI / 2; mesh.position.y = 30; mesh.position.x = 100; mesh.position.z = 120;

    house.add(mesh);

    return mesh; }

    function createDoor() { const shape = new THREE.Shape(); shape.moveTo(0, 0); shape.lineTo(0, 80); shape.lineTo(50,80); shape.lineTo(50,0); shape.lineTo(0, 0);

    const hole = new THREE.Path(); hole.moveTo(5,5); hole.lineTo(5, 75); hole.lineTo(45, 75); hole.lineTo(45, 5); hole.lineTo(5, 5); shape.holes.push(hole);

    const extrudeGeometry = new THREE.ExtrudeGeometry( shape );

    const material = new THREE.MeshBasicMaterial( { color: 'silver' } );

    const door = new THREE.Mesh( extrudeGeometry, material ) ;

    door.rotation.y = Math.PI / 2; door.position.y = 0; door.position.x = 100; door.position.z = 230;

    house.add(door); }

    function createBed() { var loader = new FBXLoader(); loader.load(host + '/bed.fbx', function ( object ) { object.position.x = 40; object.position.z = 80; object.position.y = 20;

    house.add( object ); } ); }

    const clock = new THREE.Clock();

    const controls = new FirstPersonControls(camera, renderer.domElement); controls.lookSpeed = 0.05; controls.movementSpeed = 100; controls.lookVertical = false;

    create() render()

    function render() { const delta = clock.getDelta(); controls.update(delta);

    renderer.render(scene, camera); requestAnimationFrame(render) }

    完整源码:GitHub

    小结

    • 本文提供第一人称房屋完整 Three.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/16 13:28:26

C++结构体详解:从数据聚合到轻量类,掌握高效编程核心

1. 从“数据孤岛”到“数据聚合体”:为什么我们需要结构体?如果你写过一段时间的C,尤其是处理过稍微复杂一点的数据,比如一个学生的信息(姓名、学号、成绩),或者一个游戏角色的属性(…

作者头像 李华
网站建设 2026/7/16 13:28:14

从信号到系统:数电与模电的底层逻辑与融合之道

1. 信号的本质:连续与离散的哲学对话当你用手机录制一段语音时,麦克风捕捉到的声波是平滑起伏的曲线;而当你播放这段录音时,手机处理器却在用一堆0和1来还原声音。这背后隐藏着电子世界最根本的哲学命题——模拟信号与数字信号的二…

作者头像 李华
网站建设 2026/7/16 13:28:03

终极指南:通过Loss曲线精准判断Guided Diffusion模型收敛状态

终极指南:通过Loss曲线精准判断Guided Diffusion模型收敛状态 【免费下载链接】guided-diffusion 项目地址: https://gitcode.com/gh_mirrors/gu/guided-diffusion 掌握扩散模型训练收敛判断的完整实战图谱,避免无效训练时间浪费。Guided Diffus…

作者头像 李华
网站建设 2026/7/16 13:27:30

Prompt Engineering实战:提升大模型性能的关键技术

1. Prompt Engineering:从基础概念到实战应用在2023年的大模型技术爆发中,Prompt Engineering(提示工程)已经从少数研究者的专有技能变成了每个AI从业者的必修课。我至今记得第一次用ChatGPT时,输入"写首诗"…

作者头像 李华
网站建设 2026/7/16 13:26:38

企业网站建设费用详解:从域名到开发,预算该如何规划?

企业建设网站的费用并非一成不变,其核心定价逻辑在于“需求决定价值”。功能越复杂、设计要求越高、定制化越强,相应的投入自然也会水涨船高。为了帮助企业主更清晰地规划预算,我们将网站建设的费用构成拆解如下:一、 影响价格的底…

作者头像 李华
网站建设 2026/7/16 13:25:41

Linux性能优化实战:从核心概念到调优技巧

1. Linux性能优化核心概念解析性能优化是Linux系统管理员和开发人员的必修课。在开始具体优化前,我们需要明确几个核心概念:**吞吐量(Throughput)和延迟(Latency)**是评估系统性能的两个关键指标。吞吐量指单位时间内系统处理的请求数量,而延…

作者头像 李华