You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Three.js中创建高性能高亮发光二十面体

问题描述

我想要在Three.js中创建高亮发光的二十面体几何体(Icosahedron Geometry)。目前的实现方式是将使用MeshStandardMaterial(透明度0.5)的二十面体加入Group,再通过三层循环添加27个PointLight来实现发光效果——视觉效果符合预期,但运行帧率极低(<1fps)。我希望移除这些灯光,寻求一种高性能的替代方案来实现类似效果(要求类似无限宝石的发光,且更亮、尺寸更大)。

原实现代码

import { AdditiveBlending, FrontSide, MeshStandardMaterial } from "three";
import { ShaderMaterial } from "three";
import { Group } from "three";
import { AmbientLight } from "three";
import { Color } from "three";
import { PointLight } from "three";
import { IcosahedronGeometry } from "three";
import { Mesh, PerspectiveCamera, Scene, WebGLRenderer } from "three";

const container = document.body;

const scene = new Scene();

const fov = 35;
const aspect = container.clientWidth / container.clientHeight;
const near = 0.1;
const far = 10000;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 100);

const renderer = new WebGLRenderer();
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.setPixelRatio(window.devicePixelRatio);

const tp = performance.now();

const stoneConfigs = {
  red: {
    geometry: new IcosahedronGeometry(10, 0),
    material: new MeshStandardMaterial({
      color: new Color("red"),
      opacity: 0.5,
    }),
    position: [-24, 0, 0],
    color1: new Color("red"),
    update: function () {
      // this.position.z -= 0.1;

      this.rotation.y = (performance.now() - tp) * 0.0001;
    },
  },
  blue: {
    geometry: new IcosahedronGeometry(10, 0),
    material: new MeshStandardMaterial({
      color: 0x0000ff,
      opacity: 0.5,
    }),
    position: [24, 0, 0],
    color1: 0x0000ff,
    update: function () {
      // this.position.z -= 0.1;

      this.rotation.y = (performance.now() - tp) * 0.0001;
    },
  },
  yellow: {
    geometry: new IcosahedronGeometry(10, 0),
    material: new MeshStandardMaterial({
      color: 0xffff00,
      opacity: 0.5,
    }),
    position: [0, 0, 0],
    color1: 0xffdd00,
    update: function () {
      // this.position.z -= 0.1;

      this.rotation.y = (performance.now() - tp) * 0.1;
    },
  },
};

let stones = [];

appendStones();

function appendStones() {
  for (let stoneName in stoneConfigs) {
    const stoneConfig = stoneConfigs[stoneName];

    const stoneGroup = new Group();

    const stone = new Mesh(stoneConfig.geometry, stoneConfig.material);
    stoneGroup.add(stone);

    for (let xPos = -1; xPos < 2; xPos++) {
      for (let yPos = -1; yPos < 2; yPos++) {
        for (let zPos = -1; zPos < 2; zPos++) {
          const light = new PointLight(stoneConfig.color1, 6, 10);
          light.position.set(xPos * -10, yPos * -10, zPos * -10);
          stoneGroup.add(light);
        }
      }
    }

    stoneGroup.position.set(...stoneConfig.position);

    stones.push({ stoneConfig, stone: stoneGroup });
    scene.add(stoneGroup);
  }
}

requestAnimationFrame(function render() {
  renderer.render(scene, camera);

  stones.forEach(({ stoneConfig, stone }) => {
    stoneConfig.update.bind(stone)();
  });

  requestAnimationFrame(render);
});

addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);

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

container.append(renderer.domElement);
高性能替代方案

核心思路是用材质和后期处理替代实时光源,实时光源(尤其是批量点光源)会大幅增加Draw Call和光照计算开销,而材质/后期方案是GPU友好的高效实现方式。

方案1:多层Mesh+ additive混合(快速实现基础发光)

给每个二十面体添加两层Mesh,分别负责实体质感和发光光晕:

  1. 内层:保留原半透明MeshStandardMaterial的二十面体,维持实体形态
  2. 外层:尺寸更大的二十面体,使用MeshBasicMaterial开启AdditiveBlending,模拟柔和光晕

修改appendStones函数示例:

function appendStones() {
  for (let stoneName in stoneConfigs) {
    const stoneConfig = stoneConfigs[stoneName];

    const stoneGroup = new Group();

    // 内层实体
    const stone = new Mesh(stoneConfig.geometry, stoneConfig.material);
    stoneGroup.add(stone);

    // 外层发光光晕
    const glowGeometry = new IcosahedronGeometry(12, 0); // 比内层大2单位
    const glowMaterial = new MeshBasicMaterial({
      color: stoneConfig.color1,
      transparent: true,
      opacity: 0.3,
      blending: AdditiveBlending,
      side: FrontSide
    });
    const glowMesh = new Mesh(glowGeometry, glowMaterial);
    stoneGroup.add(glowMesh);

    stoneGroup.position.set(...stoneConfig.position);
    stones.push({ stoneConfig, stone: stoneGroup });
    scene.add(stoneGroup);
  }
}

方案2:自定义ShaderMaterial(精细控制发光效果)

用自定义Shader实现基于顶点距离的渐变发光,能模拟无限宝石那种"能量汇聚"的动态效果,比多层Mesh更灵活。

示例ShaderMaterial:

const glowShader = {
  uniforms: {
    color: { value: new Color("red") },
    innerRadius: { value: 10 },
    outerRadius: { value: 15 },
    intensity: { value: 2 }
  },
  vertexShader: `
    varying vec3 vPosition;
    void main() {
      vPosition = position;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
  fragmentShader: `
    uniform vec3 color;
    uniform float innerRadius;
    uniform float outerRadius;
    uniform float intensity;
    varying vec3 vPosition;
    
    void main() {
      float dist = length(vPosition);
      // 内半径内全亮,外半径外透明,中间平滑过渡
      float alpha = smoothstep(outerRadius, innerRadius, dist) * intensity;
      gl_FragColor = vec4(color, alpha);
    }
  `,
  transparent: true,
  blending: AdditiveBlending,
  side: FrontSide
};

// 使用时替换外层光晕材质
const glowMaterial = new ShaderMaterial(glowShader);

方案3:UnrealBloomPass后期处理(真实光晕扩散)

如果需要更自然的光晕扩散效果,推荐使用Three.js官方的UnrealBloomPass后期处理,只需标记自发光物体,就能实现全局发光效果,性能远优于实时光源。

实现步骤:

  1. 引入后期处理相关模块
  2. 创建效果合成器,添加渲染通道和Bloom通道
  3. 给实体材质添加自发光属性控制发光强度

代码示例:

import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';

// 初始化后期合成器
const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);

// 配置Bloom参数:强度、半径、阈值
const bloomPass = new UnrealBloomPass(
  new THREE.Vector2(window.innerWidth, window.innerHeight),
  1.5,
  0.4,
  0.85
);
composer.addPass(bloomPass);

// 修改实体材质为带自发光的版本
const stoneMaterial = new MeshStandardMaterial({
  color: new Color("red"),
  opacity: 0.5,
  transparent: true,
  emissive: new Color("red"),
  emissiveIntensity: 3 // 数值越高,发光越明显
});

// 渲染循环替换为合成器渲染
requestAnimationFrame(function render() {
  composer.render();
  
  stones.forEach(({ stoneConfig, stone }) => {
    stoneConfig.update.bind(stone)();
  });

  requestAnimationFrame(render);
});

额外性能优化点

  • 彻底移除所有PointLight,避免光照计算开销
  • 保持二十面体的细分参数为0(IcosahedronGeometry(10, 0)),减少顶点数量
  • 若对画质要求不高,可关闭WebGLRenderer的antialias,或降低pixelRatio
  • 静态几何体默认使用BufferGeometry(Three.js r155+已默认支持),提升渲染效率

内容的提问来源于stack exchange,提问作者Hit and Run

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 09:10:04