惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

TaoSecurity Blog
TaoSecurity Blog
Jina AI
Jina AI
雷峰网
雷峰网
月光博客
月光博客
The GitHub Blog
The GitHub Blog
WordPress大学
WordPress大学
B
Blog RSS Feed
美团技术团队
C
CXSECURITY Database RSS Feed - CXSecurity.com
小众软件
小众软件
Security Latest
Security Latest
Microsoft Azure Blog
Microsoft Azure Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
Last Week in AI
Last Week in AI
A
Arctic Wolf
Latest news
Latest news
Attack and Defense Labs
Attack and Defense Labs
I
Intezer
F
Fortinet All Blogs
罗磊的独立博客
MongoDB | Blog
MongoDB | Blog
Webroot Blog
Webroot Blog
S
Secure Thoughts
Help Net Security
Help Net Security
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
V
Visual Studio Blog
P
Proofpoint News Feed
博客园 - 【当耐特】
P
Privacy International News Feed
V
Vulnerabilities – Threatpost
Stack Overflow Blog
Stack Overflow Blog
Know Your Adversary
Know Your Adversary
云风的 BLOG
云风的 BLOG
Hacker News: Ask HN
Hacker News: Ask HN
L
LINUX DO - 最新话题
H
Help Net Security
爱范儿
爱范儿
酷 壳 – CoolShell
酷 壳 – CoolShell
S
SegmentFault 最新的问题
Forbes - Security
Forbes - Security
T
Tailwind CSS Blog
量子位
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tenable Blog
Cloudbric
Cloudbric
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog

博客园 - 莫小龙

uniapp之plus.downloader.createDownload下载文件传参 谷歌之将网页保存为图片 elementui之table中相同数据的单元格合并 krpano之使用教程 threejs之灯光不跟随OrbitControls控制器旋转 threejs之将张纹理图片组成材质组 canvas之修改Base64图片中不透明部分的颜色 threejs之将PlaneGeometry转换为BufferGeometry threejs之利用shape通过线绘制面和体 threejs之添加渐变背景 paperjs之fitBounds适应区域前后屏幕坐标和输入坐标的转换 arcmap之通过点数据获取等值线 uniapp之安卓APP打开百度地图、高德地图APP openlayer之添加带箭头的线 geoserver之图片图标样式 SHP转WKT文件工具 openlayers之geoserver的wms图层mysql数据源数据修改后更新问题 通过日照时数计算每天RAD(太阳辐射)值 Uniapp之安卓签名证书(.keystore)生成
threejs之创建发光墙体
莫小龙 · 2025-06-16 · via 博客园 - 莫小龙
import * as THREE from 'three';
import bgImg from '/scene3D/bgImg.png'
import flowImg from '/scene3D/flowImg.png'
/**
 * 创建流体墙体材质
 * option =>
 * params bgUrl flowUrl
 * **/
const createWallMaterial = ({
  bgTexture,
  flowTexture
}) => {
  // 顶点着色器
  const vertexShader = `
          varying vec2 vUv;
          varying vec3 fNormal;
          varying vec3 vPosition;
          void main(){
                  vUv = uv;
                  vPosition = position;
                  vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
                  gl_Position = projectionMatrix * mvPosition;
          }
      `;
  // 片元着色器
  const fragmentShader = `
          uniform float time;
          varying vec2 vUv;
          uniform sampler2D flowTexture;
          uniform sampler2D bgTexture;
          void main( void ) {
              vec2 position = vUv;
              vec4 colora = texture2D( flowTexture, vec2( vUv.x, fract(vUv.y - time )));
              vec4 colorb = texture2D( bgTexture , position.xy);
              gl_FragColor = colorb + colorb * colora;
          }
      `;
  // 允许平铺
  flowTexture.wrapS = THREE.RepeatWrapping;
  return new THREE.ShaderMaterial({
    uniforms: {
      time: {
        value: 0,
      },
      flowTexture: {
        value: flowTexture,
      },
      bgTexture: {
        value: bgTexture,
      },
    },
    transparent: true,
    depthWrite: false,
    depthTest: false,
    side: THREE.DoubleSide,
    vertexShader: vertexShader,
    fragmentShader: fragmentShader,
  });
};
/**
 * 通过path构建墙体
 * option =>
 * params height path material expand(是否需要扩展路径)
 * **/
export const creatWallByPath = ({
  height = 10,
  path = [],
  material,
  expand = true,
}) => {
  let verticesByTwo = null;
  // 1.处理路径数据  每两个顶点为为一组
  if (expand) {
    // 1.1向y方向拉伸顶点
    verticesByTwo = path.reduce((arr, [x, y, z]) => {
      return arr.concat([
        [
          [x, y, z],
          [x, y + height, z],
        ],
      ]);
    }, []);
  } else {
    // 1.2 已经处理好路径数据
    verticesByTwo = path;
  }
  // 2.解析需要渲染的四边形 每4个顶点为一组
  const verticesByFour = verticesByTwo.reduce((arr, item, i) => {
    if (i === verticesByTwo.length - 1) return arr;
    return arr.concat([[item, verticesByTwo[i + 1]]]);
  }, []);
  // 3.将四边形面转换为需要渲染的三顶点面
  const verticesByThree = verticesByFour.reduce((arr, item) => {
    const [[point1, point2], [point3, point4]] = item;
    return arr.concat(
      ...point2,
      ...point1,
      ...point4,
      ...point1,
      ...point3,
      ...point4
    );
  }, []);
  const geometry = new THREE.BufferGeometry();
  // 4. 设置position
  const vertices = new Float32Array(verticesByThree);
  geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
  // 5. 设置uv 6个点为一个周期 [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1]

  // 5.1 以18个顶点为单位分组
  const pointsGroupBy18 = new Array(verticesByThree.length / 3 / 6)
    .fill(0)
    .map((item, i) => {
      return verticesByThree.slice(i * 3 * 6, (i + 1) * 3 * 6);
    });
  // 5.2 按uv周期分组
  const pointsGroupBy63 = pointsGroupBy18.map((item, i) => {
    return new Array(item.length / 3)
      .fill(0)
      .map((it, i) => item.slice(i * 3, (i + 1) * 3));
  });
  // 5.3根据BoundingBox确定uv平铺范围
  geometry.computeBoundingBox();
  const { min, max } = geometry.boundingBox;
  const rangeX = max.x - min.x;
  const uvs = [].concat(
    ...pointsGroupBy63.map((item) => {
      const point0 = item[0];
      const point5 = item[5];
      const distance =
        new THREE.Vector3(...point0).distanceTo(new THREE.Vector3(...point5)) /
        (rangeX / 10);
      return [0, 1, 0, 0, distance, 1, 0, 0, distance, 0, distance, 1];
    })
  );
  geometry.setAttribute(
    "uv",
    new THREE.BufferAttribute(new Float32Array(uvs), 2)
  );
  // 更新法线
  // geometry.computeVertexNormals();
  const meshMat =
    material ||
    new THREE.MeshBasicMaterial({
      color: 0x00ffff,
      side: THREE.DoubleSide,
    });
  return new THREE.Mesh(geometry, material);
};
// 创建墙体
export function createWall(path) {
  const bgTexture = new THREE.TextureLoader().load(bgImg);
  const flowTexture = new THREE.TextureLoader().load(flowImg);
  const material = createWallMaterial({
    bgTexture,
    flowTexture
  });
  const wallMesh = creatWallByPath({
    height: 10, 
    path,
    material:material
  });
  return wallMesh
}
            const path = [
                [80, 0, -40],
                [10, 0, 0],
                [60, 0, 50],
                [0, 10, 0],
                [-60, 0, 50],
                [-50, 0, -30],
                [80, 0, -40],
            ];
            scene.add(createWall(path));