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

Three.js 官方选择辉光简化版教程

官方选择辉光简化版 ·Three Bloom· ▶ 在线运行案例

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

你将学到什么

  • ShaderMaterial 自定义着色器实现核心视觉效果
  • EffectComposer 多 Pass 后期处理管线
  • UnrealBloomPass 辉光 Bloom 效果
  • OrbitControls 相机轨道交互
  • glTF/Draco 模型加载与优化
  • Raycaster 鼠标拾取与交互
  • requestAnimationFrame渲染循环与resize自适应

效果说明

本案例演示官方选择辉光简化版效果:原场景渲染后经 EffectComposer 叠加 Bloom/模糊等全屏后期,支持鼠标拾取、绘制或拖拽交互;核心用到 ShaderMaterial、EffectComposer、UnrealBloomPass。建议先打开文首在线案例查看动态画面,再对照下方源码逐步理解。

核心概念

  • Scene / Camera / WebGLRenderer构成最小渲染闭环;大场景可开logarithmicDepthBuffer缓解 Z-fighting。
  • ShaderMaterial通过uniforms+ 自定义 GLSL 控制逐像素/逐点效果;透明粒子常配合depthTest: false
  • EffectComposer以多 Pass 链式渲染:RenderPass → 特效 Pass → 输出屏幕,替代直接renderer.render
  • OrbitControls提供轨道旋转/缩放;开启enableDamping后需在 animate 中controls.update()

实现步骤

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

    import * as THREE from "three"

    import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js" import { OrbitControls } from "three/addons/controls/OrbitControls.js" import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js" import { RenderPass } from "three/addons/postprocessing/RenderPass.js" import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js" import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js"

    const renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true, }) renderer.setSize(window.innerWidth, window.innerHeight) document.body.appendChild(renderer.domElement)

    const scene = new THREE.Scene() const camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 100000) camera.position.set(200, 200, 200) new OrbitControls(camera, renderer.domElement)

    const light = new THREE.DirectionalLight(0xffffff, 3) light.position.set(100, 100, 100) scene.add(light)

    // 物体 new GLTFLoader().load(FILE_HOST + "files/model/Fox.glb", (gltf) => scene.add(gltf.scene)) const mesh = new THREE.Mesh(new THREE.BoxGeometry(20, 20, 20), new THREE.MeshStandardMaterial({ color: 0x00ff00 })) mesh.position.set(50, 0, 0) scene.add(mesh)

    // 后期处理 const renderScene = new RenderPass(scene, camera) const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 0.8, 0.4, 0.0) const bloomComposer = new EffectComposer(renderer) bloomComposer.renderToScreen = false bloomComposer.addPass(renderScene) bloomComposer.addPass(bloomPass)

    const finalPass = new ShaderPass( new THREE.ShaderMaterial({ uniforms: { baseTexture: { value: null }, bloomTexture: { value: bloomComposer.renderTarget2.texture }, }, vertexShader:varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrixmodelViewMatrixvec4( position, 1.0 ); }, fragmentShader:uniform sampler2D baseTexture; uniform sampler2D bloomTexture; varying vec2 vUv; void main() { gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) ); }, defines: {}, }), "baseTexture" ) finalPass.needsSwap = true const finalComposer = new EffectComposer(renderer) finalComposer.addPass(renderScene) finalComposer.addPass(finalPass)

    // 点击切换辉光 window.addEventListener("click", onClick) function onClick(event) { const raycaster = new THREE.Raycaster() const mouse = new THREE.Vector2( (event.offsetX / event.target.clientWidth) * 2 - 1, -(event.offsetY / event.target.clientHeight) * 2 + 1 ) raycaster.setFromCamera(mouse, camera) const intersects = raycaster.intersectObjects(scene.children) if (intersects.length > 0) intersects[0].object.layers.toggle(1) // 切换图层 }

    // 窗口大小变化 window.onresize = function () { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) bloomComposer.setSize(window.innerWidth, window.innerHeight) finalComposer.setSize(window.innerWidth, window.innerHeight) }

    // 辉光图层 const bloomLayer = new THREE.Layers() bloomLayer.set(1)

    const darkMaterial = new THREE.MeshBasicMaterial({ color: "black" }) const materials = {}

    render() function render() { requestAnimationFrame(render) scene.traverse(obj => { if (obj.isMesh && bloomLayer.test(obj.layers) === false) { materials[obj.uuid] = obj.material // 保存原材质 obj.material = darkMaterial // 替换材质 } }) bloomComposer.render() // 渲染到bloomComposer scene.traverse(obj => { if (materials[obj.uuid]) { obj.material = materials[obj.uuid] // 恢复原材质 delete materials[obj.uuid] // 删除原材质 } }) finalComposer.render() }

    完整源码:GitHub

    小结

    • 本文提供官方选择辉光简化版完整 Three.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库
http://www.jsqmd.com/news/1101956/

相关文章:

  • 国产大模型会回答之后,怎样用魔珐星云补齐具象交互?
  • 【小白也能轻松玩转龙虾】虾壳云一键部署轻量化 AI,低配设备流畅运行 OpenClaw v2.7.9(附最新安装包)
  • PowerPC评估板ASD433A硬件设计解析与调试实战
  • 3分钟实现Windows桌面分区革命:NoFences开源桌面管理终极方案
  • Visual C++运行库终极指南:一键解决Windows软件依赖问题
  • Codex 实战:从基础调用到稳定运行
  • 权限状态机与渐进式授权:从用户体验到子 Agent 代理
  • 云服务器SSRF漏洞利用IMDS窃取IAM凭证的攻防实战
  • UniExtract2:终极文件解压工具,一键提取500+种格式的完整指南
  • 花箱花坛花槽花钵哪家好?优质靠谱供应商挑选实用指南
  • 【仅限前500名开发者】OpenAI发布会技术密钥包:含Model Context Protocol v2规范、Rate Limiting 3.0策略表、Error Code映射速查表
  • 终极CSV查看指南:用csview快速美化你的数据表格
  • 测试内容测试内容测试内容
  • 微信网页版解锁插件:5分钟解决Chrome/Firefox/Edge无法登录问题
  • Sora已上线全球公测,可灵AI却悄然升级V2.3——两大平台训练成本、推理延迟、版权合规性全对比,现在不看就晚了!
  • HTML 早已不是标签了,它现在是系统级接口:这 9 个 API 直接干翻常用 JS 库 _
  • U-Net 技术详解:为什么一个 2015 年的分割网络还在被反复使用
  • VisualCppRedist AIO:5分钟解决所有Windows DLL缺失问题的终极方案
  • 面试被问到没做过的项目直接说不会?留学生如何正确回答「蒸汽求职分享」
  • 【企业级AI选型避坑指南】:OpenAI 5类商用产品(API/Chat/Assistant/Studio/Enterprise)适用场景与合规红线
  • 解放双手的明日方舟智能管理助手:MAA全功能配置终极指南
  • 终极实战指南:用Vite高效构建现代化Chrome扩展程序
  • 阴阳师脚本:百鬼夜行自动化终极方案,碎片收集效率提升300%
  • web第9次作业
  • 技术视角拆解:麦杰克繁星AC10的硬件参数与真实用户体验的对应关系
  • 零基础谷歌收录排查问题:页面发布7天没动静
  • 抖音医生黄号认证
  • 2026电商SaaS选型指南:自建 vs 订阅 vs 买断
  • 【Cursor进阶避坑手册】:踩过137次报错后总结的8个致命配置陷阱,新手3分钟规避
  • Kiran-Flameshot深度评测:为什么它是Linux上最强大的截图工具