当前位置: 首页 > news >正文

Three.js 人物虚化教程

人物虚化 ·人物虚化· ▶ 在线运行案例

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

你将学到什么

  • onBeforeCompile 注入 GLSL 改造内置材质
  • OrbitControls 相机轨道交互
  • Canvas 动态纹理贴图
  • FBXLoader 加载 FBX 城市/角色模型
  • 骨骼动画与 AnimationMixer
  • requestAnimationFrame渲染循环与resize自适应

效果说明

本案例演示人物虚化效果:用 Canvas 2D 绘制内容并实时映射为 Three.js 纹理;核心用到 onBeforeCompile、OrbitControls、Canvas。建议先打开文首在线案例查看动态画面,再对照下方源码逐步理解。

核心概念

  • Scene / Camera / WebGLRenderer构成最小渲染闭环;大场景可开logarithmicDepthBuffer缓解 Z-fighting。
  • onBeforeCompile在 Three 拼好内置 shader 后替换#include片段,适合在 PBR 材质上叠加大屏特效。
  • OrbitControls提供轨道旋转/缩放;开启enableDamping后需在 animate 中controls.update()
  • CanvasTexture每帧或按需把 2D Canvas 内容上传 GPU,适合动态文字、图表、视频帧贴图。

实现步骤

  • 搭建 Scene、PerspectiveCamera、WebGLRenderer,挂载 canvas 并处理resize
  • 异步加载模型 / 3D Tiles / GeoJSON 等资源并加入 scene 或 entities
  • 定义 uniforms / onBeforeCompile 或 ShaderMaterial,编写 GLSL 与材质参数
  • 创建 OrbitControls(及 Raycaster 等交互控件,若源码包含)
  • requestAnimationFrame循环中更新状态并 render(Cesium 为viewer.render或自动渲染)
  • 代码要点

    import * as THREE from "three";

    import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader.js"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; import { GUI } from "dat.gui";

    const modelUrl = "https://ylfq.github.io/model/walk.fbx";

    const canvas = document.createElement("canvas"); canvas.style.width = "100vw !important"; canvas.style.height = "100vh !important"; document.body.appendChild(canvas);

    const renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true, alpha: true }); renderer.setClearColor(0x333333, 0); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFShadowMap;

    const scene = new THREE.Scene();

    const loader_fbx = new FBXLoader();

    const modelMaterialUniforms = { blur: 0.85, blockSize: 12.0, };

    const model = await loader_fbx.loadAsync(modelUrl); model.traverse((obj) => { if (obj instanceof THREE.Mesh) { obj.castShadow = true; obj.receiveShadow = true;

    /* @type {THREE.MeshPhongMaterial}/ const m = obj.material; m.onBeforeCompile = (shader) => { shader.uniforms.blur = { get value() { return modelMaterialUniforms.blur; }, }; shader.uniforms.blockSize = { get value() { return modelMaterialUniforms.blockSize; }, };

    shader.fragmentShader = shader.fragmentShader.replace( /glsl/void main() {, /glsl/// 虚化阈值 uniform float blur; // 虚化区块大小 uniform float blockSize;

    // 虚化矩阵,自定义区块内的虚化顺序,当像素对应的虚化矩阵值小于blur时,该像素不进行渲染 const mat4 blurMatrix = mat4( 0.1, 0.5, 0.7, 0.3, 0.6, 0.6, 0.9, 0.8, 0.8, 1.0, 0.2, 0.6, 0.3, 0.7, 0.5, 0.4 ); void main() { ivec2 xyInBlur = ivec2(fract(gl_FragCoord.xy / blockSize) * 4.0); if (blurMatrix[xyInBlur.y][xyInBlur.x] <= blur) discard;); }; } }); const mixer = new THREE.AnimationMixer(model); const action = mixer.clipAction(model.animations[0]); action.setLoop(THREE.LoopRepeat); action.play();

    const light_ambient = new THREE.AmbientLight(0xffffff, 0.7);

    const light_directional = new THREE.DirectionalLight(0xffffff, 0.8); light_directional.position.set(200, 200, 200); light_directional.castShadow = true; light_directional.shadow.camera.left = -100; light_directional.shadow.camera.right = 100; light_directional.shadow.camera.top = 100; light_directional.shadow.camera.bottom = -100; light_directional.shadow.camera.near = 1; light_directional.shadow.camera.far = 1000; light_directional.shadow.mapSize.width = 1024; light_directional.shadow.mapSize.height = 1024;

    scene.add(model, light_ambient, light_directional);

    const camera = new THREE.PerspectiveCamera(90, 1, 0.1, 1000); camera.position.set(0, 0, 140);

    const controls = new OrbitControls(camera, canvas); controls.enableDamping = true;

    const timer = new THREE.Timer();

    const tick = (delta, elapsed) => { controls.update(delta);

    // 更新动画并限制模型不进行移动 mixer.update(delta * 0.9); model.children[2].children[0].position.set(0, 0, 0); };

    const render = () => { renderer.render(scene, camera); };

    const ani = () => { const elapsed = timer.getElapsed(); const delta = timer.getDelta();

    timer.update();

    tick(delta, elapsed); render();

    requestAnimationFrame(ani); };

    const data = { get blur() { return modelMaterialUniforms.blur; }, set blur(v) { modelMaterialUniforms.blur = v; },

    get blockSize() { return modelMaterialUniforms.blockSize; }, set blockSize(v) { modelMaterialUniforms.blockSize = v; }, }; const gui = new GUI(); gui.add(data, "blur", 0, 1, 0.001).name("虚化强度"); gui.add(data, "blockSize", 2.0, 20.0, 4.0).name("虚化区块大小");

    new ResizeObserver(() => { const rect = document.body.getBoundingClientRect(); const w = rect.width; const h = rect.height; const a = w / h; const dpr = window.devicePixelRatio * 1.25;

    renderer.setSize(w, h, false); renderer.setPixelRatio(dpr);

    camera.aspect = a; camera.updateProjectionMatrix(); }).observe(document.body);

    ani();

    完整源码:GitHub

    小结

    • 本文提供人物虚化完整 Three.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库
http://www.gsyq.cn/news/1621411.html

相关文章:

  • 开源通用漏洞扫描器Sirius Scan:从架构解析到CI/CD集成的实战指南
  • 6DoF运动追踪:IIM-42652 IMU与PIC32微控制器实战
  • 基于74HC32与PIC18F97J60的2x2矩阵键盘设计
  • 基于TPAFE0808和MK51DN512的多通道信号采集系统设计
  • QMcDump:终极QQ音乐加密文件解码工具完整指南
  • AI工具如何解决本科毕业论文写作三大痛点
  • 基于Si4732与PIC18F2525的高保真收音机设计
  • 中国车牌生成器:快速生成逼真车牌图像的终极解决方案
  • 基于Si4731与STM32的数字收音机设计与实现
  • RPG Maker游戏解密终极指南:3步轻松提取加密资源
  • MuleSoft+LLM企业级AI编排:打通系统孤岛与语义断层
  • Sqribble文档流水线:模板驱动的结构化PDF生成系统
  • 基于Si4731与PIC18F2585的数字收音机系统设计与实现
  • 炉石传说脚本:5分钟掌握自动化游戏秘籍,解放你的双手!
  • QQ音乐格式转换终极指南:qmcdump轻松解密加密音频
  • 基于STM32与Si4731的数字收音机系统设计与实现
  • 认准中华土蜂!这瓶旋转蜂蜜水,和普通意蜂蜜水根本不是一回事
  • 基于Si4731与PIC18F86J50的可编程FM收音机系统设计
  • 13DOF传感器与PIC18F2525实现低成本高精度定位导航
  • 3步轻松搞定音乐歌词批量下载:免费开源工具解决你的歌词烦恼
  • Ansys Motor-CAD 15.1.2 安装激活全套流程
  • 【每日学术速报】2026-06-29|从人力密集到系统自足:医学AI的数据解放与机器人学习的研究自主化
  • 如何用Fate/Grand Automata实现FGO自动化:新手5分钟上手指南
  • 模板驱动型文档自动化:企业级文档工程化实践
  • 2026汉中黄金回收白银回收铂金回收旧料回收怎么选?五家高实价铂金白银线下门店测评清单 + 联系方式
  • Sqribble:面向技术从业者的确定性PDF自动化排版系统
  • AD74413R与STM32F410RB高精度数据采集方案解析
  • 解耦异构算力!基于 Docker + GB28181/RTSP 的企业级 AI 视频管理平台架构演进与源码交付实践
  • 传统javaweb项目部署
  • 游戏装备交易小程序开发定制