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

如何在Three.js中创建可透光网格物体(实现类灯具效果)

嘿,作为Three.js新手能想到用BoxGeometry起步已经很棒啦!我来帮你调整代码,实现你要的网格状平面透光散射的灯具效果,一步步来:

实现网格透光散射效果的具体方案

你的核心需求是:正前方相机视角下的网格平面,后方灯光透过网格产生散射,类似磨砂灯具的质感。咱们从几何体、材质、光源三个核心部分调整:

1. 把立方体换成网格平面(两种可选方式)

因为相机在正前方,完全不需要3D立方体,用平面就能搞定,这里给你两种实现网格的思路:

方式一:用平面+Canvas纹理做镂空网格

适合想要“一块面板上有网格镂空”的效果,我们用Canvas生成网格纹理,通过alphaMap让网格线条部分透明:

// 创建平面几何体,尺寸你可以自己调整(这里是2x2)
const geometry = new THREE.PlaneGeometry(2, 2);

// 用Canvas生成网格纹理
const canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 256;
const ctx = canvas.getContext('2d');
// 先画白色背景(不透明区域)
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, 256, 256);
// 再画黑色网格线条(透明区域)
ctx.fillStyle = '#000000';
const gridSize = 32; // 网格间距,数值越小网格越密
// 画横向线条
for (let x = 0; x <= 256; x += gridSize) {
  ctx.fillRect(x, 0, 2, 256); // 线条宽度是2,你可以改
}
// 画纵向线条
for (let y = 0; y <= 256; y += gridSize) {
  ctx.fillRect(0, y, 256, 2);
}
// 把Canvas转成Three.js纹理
const gridTexture = new THREE.CanvasTexture(canvas);

方式二:用多个小平面拼接成网格

适合想要“由独立小方块组成网格”的效果,后续可以给每个小方块加单独动画或材质:

const gridGroup = new THREE.Group(); // 用Group统一管理所有小方块
const gridCount = 8; // 网格的行列数,比如8x8
const cellSize = 0.2; // 每个小方块的尺寸
const gap = 0.05; // 方块之间的间距

// 循环创建小平面
for (let x = 0; x < gridCount; x++) {
  for (let y = 0; y < gridCount; y++) {
    const cellGeometry = new THREE.PlaneGeometry(cellSize, cellSize);
    const cellMaterial = /* 后面讲材质 */;
    const cellMesh = new THREE.Mesh(cellGeometry, cellMaterial);
    // 计算位置,让方块排列成居中的网格
    cellMesh.position.x = (x - (gridCount - 1)/2) * (cellSize + gap);
    cellMesh.position.y = (y - (gridCount - 1)/2) * (cellSize + gap);
    gridGroup.add(cellMesh);
  }
}
scene.add(gridGroup); // 把整个网格组加到场景里

2. 选对材质才能实现透光散射

要做出“光线透过网格散射”的磨砂效果,**MeshPhysicalMaterial**是最佳选择,它支持真实的光线透射和粗糙度调节,比普通的opacity透明效果更自然:

const material = new THREE.MeshPhysicalMaterial({
  color: 0xffffff, // 白色材质最容易透出灯光的颜色,你也可以换其他浅色调
  transmission: 0.9, // 透射率,0-1之间,越高越透明
  roughness: 0.7, // 粗糙度,越高散射效果越强(磨砂感越重)
  side: THREE.DoubleSide, // 平面默认只有正面可见,开启双面避免视角问题
  transparent: true, // 如果用方式一的alphaMap,必须开这个
  alphaMap: gridTexture, // 方式一需要加这个,方式二不用
});

划重点:别用MeshPhongMaterial啦,它不支持transmission,做不出真实的散射透光效果。

3. 添加后方光源并优化细节

把光源放在网格的后方,再开启阴影增强真实感:

// 创建暖白色点光源,参数分别是颜色、强度、照射范围
const light = new THREE.PointLight(0xfff8dc, 2, 10);
light.position.z = 1; // 假设网格在z=0位置,把光源放在后方(z正方向)
light.castShadow = true; // 开启阴影,让透光效果更有层次
scene.add(light);

// 给网格开启接收阴影(方式一直接给gridMesh加,方式二要循环给每个cellMesh加)
gridMesh.receiveShadow = true;

4. 调整相机和渲染器的基础设置

别忘了给渲染器开启阴影,相机放在正前方合适的位置:

// 相机位置(放在网格正前方,z轴3的位置,你可以根据尺寸调整)
camera.position.z = 3;

// 渲染器开启软阴影,效果更自然
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

完整可运行代码示例(用方式一)

把这些整合起来,替换你原来的代码就行:

// 初始化基础组件
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);

// 1. 创建带网格纹理的平面
const geometry = new THREE.PlaneGeometry(2, 2);
const canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 256;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, 256, 256);
ctx.fillStyle = '#000000';
const gridSize = 32;
for (let x = 0; x <= 256; x += gridSize) {
  ctx.fillRect(x, 0, 2, 256);
}
for (let y = 0; y <= 256; y += gridSize) {
  ctx.fillRect(0, y, 256, 2);
}
const gridTexture = new THREE.CanvasTexture(canvas);

// 2. 透光磨砂材质
const material = new THREE.MeshPhysicalMaterial({
  color: 0xffffff,
  transmission: 0.9,
  roughness: 0.7,
  alphaMap: gridTexture,
  transparent: true,
  side: THREE.DoubleSide,
});
const gridMesh = new THREE.Mesh(geometry, material);
gridMesh.receiveShadow = true;
scene.add(gridMesh);

// 3. 后方光源
const light = new THREE.PointLight(0xfff8dc, 2, 10);
light.position.z = 1;
light.castShadow = true;
scene.add(light);

// 4. 相机位置
camera.position.z = 3;

// 动画循环
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

小技巧

  • 如果想要更强的散射效果,可以把roughness调到0.8-0.9;如果想要更通透的效果,就降低roughness。
  • 可以试试把PointLight换成SpotLight,模拟射灯的聚焦效果。
  • 如果用方式二的网格组,想要每个小方块的散射效果更明显,可以给每个方块加一点点厚度(用BoxGeometry代替PlaneGeometry,厚度设小一点比如0.01)。

内容的提问来源于stack exchange,提问作者gwen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:54:02