Threejs围墙动画

难点1:

根据顶点构建出来的围墙,默认是z轴朝上。假如模型是y轴朝上,则不好控制围墙的边界顶点。
这里的思路是 把模型绕x轴翻转90度,然后根据rayser射线选取顶点。根据顶点构建完围墙后,再把围墙mesh翻转90度回来

代码:

function addShape() {let c = [53.95640312236819, 193.4562016693937, 123.4327246849135, 187.81369736193992,125.41600819650955, 218.75893553744257, 51.14432668036085, 223.0195030041947, 53.95640312236819, 193.4562016693937];let posArr = [];let uvrr = [];let h = 10; //围墙拉伸高度for (let i = 0; i < c.length - 2; i += 2) {// 围墙多边形上两个点构成一个直线扫描出来一个高度为h的矩形// 矩形的三角形1posArr.push(c[i], c[i + 1], 0, c[i + 2], c[i + 3], 0, c[i + 2], c[i + 3], h);// 矩形的三角形2posArr.push(c[i], c[i + 1], 0, c[i + 2], c[i + 3], h, c[i], c[i + 1], h);// 注意顺序问题,和顶点位置坐标对应uvrr.push(0, 0, 1, 0, 1, 1);uvrr.push(0, 0, 1, 1, 0, 1);}let geometry = new THREE.BufferGeometry(); //声明一个空几何体对象// 设置几何体attributes属性的位置position属性geometry.attributes.position = new THREE.BufferAttribute(new Float32Array(posArr), 3);// 设置几何体attributes属性的位置uv属性geometry.attributes.uv = new THREE.BufferAttribute(new Float32Array(uvrr), 2);geometry.computeVertexNormals()let mesh = new THREE.Mesh(geometry, custMaterial); //网格模型对象Meshscene.add(mesh);mesh.rotateX(-Math.PI / 2);

难点2:

围墙的shader编写,这个shader是拷贝的maptalks里面的围墙shader,查看源代码直接拿来用即可。
代码:

const vertexs = {normal_vertex: "\n  precision lowp float;\n  precision lowp int;\n  ".concat(THREE.ShaderChunk.fog_pars_vertex,"\n  varying vec2 vUv;\n  void main() {\n    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n    vUv = uv;\n    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    ").concat(THREE.ShaderChunk.fog_vertex, "\n  }\n"),
};const fragments = {rippleWall_fragment:"\n  precision lowp float;\n  precision lowp int;\n  uniform float time;\n  uniform float opacity;\n  uniform vec3 color;\n  uniform float num;\n  uniform float hiz;\n\n  varying vec2 vUv;\n\n  void main() {\n    vec4 fragColor = vec4(0.);\n    float sin = sin((vUv.y - time * hiz) * 10. * num);\n    float high = 0.92;\n    float medium = 0.4;\n    if (sin > high) {\n      fragColor = vec4(mix(vec3(.8, 1., 1.), color, (1. - sin) / (1. - high)), 1.);\n    } else if(sin > medium) {\n      fragColor = vec4(color, mix(1., 0., 1.-(sin - medium) / (high - medium)));\n    } else {\n      fragColor = vec4(color, 0.);\n    }\n\n    vec3 fade = mix(color, vec3(0., 0., 0.), vUv.y);\n    fragColor = mix(fragColor, vec4(fade, 1.), 0.85);\n    gl_FragColor = vec4(fragColor.rgb, fragColor.a * opacity * (1. - vUv.y));\n  }\n",
};const custMaterial = new THREE.ShaderMaterial({uniforms: {time: {type: "pv2",value: 0,},color: {type: "uvs",value: new THREE.Color("#FF4127"),},opacity: {type: "pv2",value: 1.0,},num: {type: "pv2",value: 10,},hiz: {type: "pv2",value: 0.15,},},vertexShader: vertexs.normal_vertex,fragmentShader: fragments.rippleWall_fragment,blending: THREE.AdditiveBlending,transparent: !0,depthWrite: !1,depthTest: !0,side: THREE.DoubleSide,
});

然后循环函数里面控制时间参数。

function animal() {renderer.render(scene, camera)if (custMaterial) {custMaterial.uniforms.time.value += 0.015;}requestAnimationFrame(animal)
}

demo代码
shader代码来源于maptalks

<template><div ref="test" class="test"></div>
</template><script setup>import * as THREE from "three";
import {onMounted, ref} from "vue";
import {MapControls} from 'three/examples/jsm/controls/OrbitControls'const vertexs = {normal_vertex: "\n  precision lowp float;\n  precision lowp int;\n  ".concat(THREE.ShaderChunk.fog_pars_vertex,"\n  varying vec2 vUv;\n  void main() {\n    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n    vUv = uv;\n    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    ").concat(THREE.ShaderChunk.fog_vertex, "\n  }\n"),
};const fragments = {rippleWall_fragment:"\n  precision lowp float;\n  precision lowp int;\n  uniform float time;\n  uniform float opacity;\n  uniform vec3 color;\n  uniform float num;\n  uniform float hiz;\n\n  varying vec2 vUv;\n\n  void main() {\n    vec4 fragColor = vec4(0.);\n    float sin = sin((vUv.y - time * hiz) * 10. * num);\n    float high = 0.92;\n    float medium = 0.4;\n    if (sin > high) {\n      fragColor = vec4(mix(vec3(.8, 1., 1.), color, (1. - sin) / (1. - high)), 1.);\n    } else if(sin > medium) {\n      fragColor = vec4(color, mix(1., 0., 1.-(sin - medium) / (high - medium)));\n    } else {\n      fragColor = vec4(color, 0.);\n    }\n\n    vec3 fade = mix(color, vec3(0., 0., 0.), vUv.y);\n    fragColor = mix(fragColor, vec4(fade, 1.), 0.85);\n    gl_FragColor = vec4(fragColor.rgb, fragColor.a * opacity * (1. - vUv.y));\n  }\n",
};const custMaterial1 = new THREE.ShaderMaterial({uniforms: {time: {type: "pv2",value: 0,},color: {type: "uvs",value: new THREE.Color("#FF4127"),},opacity: {type: "pv2",value: 1.0,},num: {type: "pv2",value: 10,},hiz: {type: "pv2",value: 0.15,},},vertexShader: vertexs.normal_vertex,fragmentShader: fragments.rippleWall_fragment,blending: THREE.AdditiveBlending,transparent: !0,depthWrite: !1,depthTest: !0,side: THREE.DoubleSide,
});let test =  ref(null), renderer, scene, camera, controls, pmremGeneratoronMounted(() => {initModel();test.value.appendChild(renderer.domElement)animal();
})function animal() {renderer.render(scene, camera)if (custMaterial1) {custMaterial1.uniforms.time.value += 0.015;}requestAnimationFrame(animal)
}function initModel() {renderer = new THREE.WebGLRenderer({antialias: true, //开启锯齿})renderer.physicallyCorrectLights = true;renderer.outputEncoding = THREE.sRGBEncoding;renderer.toneMapping = THREE.ACESFilmicToneMapping;renderer.toneMappingExposure = 0.85renderer.shadowMap.enabled = true;renderer.shadowMap.type = THREE.PCFSoftShadowMap;let width = test.value.clientWidthlet height = test.value.clientHeightrenderer.setPixelRatio(window.devicePixelRatio) //设置设备像素比率,防止Canvas画布输出模糊。renderer.setSize(width, height) //设置渲染区域尺寸scene = new THREE.Scene()camera = new THREE.PerspectiveCamera(30, width / height, 1, 40000)camera.up.set(0, 0 ,1)controls = new MapControls(camera, renderer.domElement)camera.position.set(50, 50, 50)addShape()scene.add(new THREE.AxesHelper(50))let ambient = new THREE.AmbientLight(0xffffff, 0.8)scene.add(ambient)const hemiLight = new THREE.HemisphereLight(0x00AAFF, 0xFFAA00, 0.8);scene.add(hemiLight);console.log(scene)
}function addShape() {let c = [0,0, 10, 0, 10, 10, 0, 10, 0, 0]let posArr = [];let uvrr = [];let h = 10; //围墙拉伸高度for (let i = 0; i < c.length - 2; i += 2) {// 围墙多边形上两个点构成一个直线扫描出来一个高度为h的矩形// 矩形的三角形1posArr.push(c[i], c[i + 1], 0, c[i + 2], c[i + 3], 0, c[i + 2], c[i + 3], h);// 矩形的三角形2posArr.push(c[i], c[i + 1], 0, c[i + 2], c[i + 3], h, c[i], c[i + 1], h);// 注意顺序问题,和顶点位置坐标对应uvrr.push(0, 0, 1, 0, 1, 1);uvrr.push(0, 0, 1, 1, 0, 1);}let geometry = new THREE.BufferGeometry(); //声明一个空几何体对象// 设置几何体attributes属性的位置position属性geometry.attributes.position = new THREE.BufferAttribute(new Float32Array(posArr), 3);// 设置几何体attributes属性的位置uv属性geometry.attributes.uv = new THREE.BufferAttribute(new Float32Array(uvrr), 2);geometry.computeVertexNormals()let custMaterial = new  THREE.MeshLambertMaterial({color: 0X049ef4,side : THREE.DoubleSide})let mesh = new THREE.Mesh(geometry, custMaterial1); //网格模型对象Meshscene.add(mesh);// mesh.rotateX(-Math.PI / 2);}</script><style scoped lang="less">
.test {height: 100%;
}
</style>

Threejs围墙动画相关推荐

  1. json动画_three.js动画(四)

    ThreeJS的动画系列分为:基础动画.相机控制.变形动画.用骨骼和蒙皮制作动画以及使用外部模型创建动画. 用骨骼和蒙皮制作动画 用骨骼来做动画时,移动一下骨骼,Three.js必须决定如何相应地迁移 ...

  2. threejs骨架形状

    骨骼动画 骨骼是什么?骨骼就是一个可以控制其它形状的对象.在threejs中,骨骼(Bone)就是一个空的Object3D对象,当然,也可以是任何Object3D对象的子类. 创建骨架 创建骨架总体来 ...

  3. ThreeJs 3D编程

    新版本的主流浏览器都已支持WebGL,这样不需要插件就能在浏览器中创建三维图形.但WebGL提供的接口过于复杂,直接使用来创建三维图形和动画非常繁琐.Three.js函数库将强大的功能融汇其中,方便使 ...

  4. three.js动画(Animation)

    导航 一.three.js的动画解析基本流程 二.各部分功能介绍 三.threejs的动画类型 四.threejs对动画的处理过程 一.three.js的动画解析基本流程 var mesh; //导出 ...

  5. 使用threejs简单Web3D效果

    目录 1. threejs介绍 2. thresjs的使用 3. 组件介绍 4. threejs的动画 5. 参考资料 前几天在网上看到一个threejs的实现的web 3d的动画,很炫酷,所以特地去 ...

  6. 视频教程-WebGL 可视化3D绘图框架:Three.js 零基础上手实战-其他

    WebGL 可视化3D绘图框架:Three.js 零基础上手实战 网名风舞烟,中国科技大学计算机专业.微软认证讲师(MCE).微软数据分析讲师.10多年软件行业从业经验,参与过数百万的企业级ERP系统 ...

  7. 基于Web SCADA平台构建实时数字化产线 - 初篇

           如各位对Web SCADA平台及技术感兴趣,欢迎转发或私信我,大家共同学习,相互交流共同进步:  构建数字化产线是近几年国家推出两化融化后.智能制造等相应政策后的产物,传统的信息化.工业 ...

  8. Three.js模拟沿着路径进行运动,模拟飞机飞行,并保持运动方向

    1,介绍 该示例使用的是 r95版本Three.js库. 主要实现功能:加载飞机模型,初始化任意轨迹线路,沿着轨迹进行运动并保持方向. 效果图如下: ​​​2,主要说明 曲线通过三维样条曲线曲线类TH ...

  9. Three.js零基础入门教程(2023版本)

    1. threejs文件包下载和目录简介 在正式学习Three.js之前,先做一些必要的准备工作,具体说就是下载threejs官方文件包,threejs官方文件包提供了很多有用的学习资源. Three ...

最新文章

  1. LSTM登顶20世纪AI论文高引No.1,NLP技术崛起!!!
  2. python ln2怎么写_Python2和3切换默认
  3. MATLAB实战系列(五)-模拟退火(SA)算法求解旅行商 (TSP)问题MATLAB代码讲解
  4. keypair java_如何在Java中序列化和反序列化RSA KeyPair
  5. 文件上传优化CommonsMultipartResolver
  6. IPV6迎来商业元年 运营商短期盈利模式成难点
  7. 在.NET Core中使用Exceptionless分布式日志收集框架
  8. 查看.Net Framework版本的方法
  9. 真机调试时部分日志丢失(魅族)
  10. 01 Oracle 导入SQL文件
  11. 使用Xftp连接Linux
  12. 完美世界服务器维护多久,完美世界服务端启动和维护
  13. uniapp 获取时间戳
  14. dart语言和flutter学习——Dart语言学习
  15. XML 格式化转字符串
  16. Kotlin协程核心库分析-5 Job异常处理器注意点
  17. openwrt软路由实现ipv6 nat 上网配置
  18. 解决(Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.4:ins)
  19. R语言实战笔记 基本统计分析-频数列联表和简单的独立性检验
  20. 通用键盘鼠标模拟(包括USB和PS2)

热门文章

  1. 常见的 App 安全问题
  2. 计算机 学院派,总校计算机学院派老师来校召开“2+2”联合培养班学生见面会...
  3. 科学计算机隐藏功能,经常用手机计算器的抓紧看看,原来还隐藏着3个功能,涨知识了...
  4. EFR32上用DMA实现UART高速数据传输
  5. 操作系统学习笔记(13) 互斥与同步的经典问题 -哲学家进餐问题
  6. 前端开发的流程与规范
  7. 【洛谷】 P1424 小鱼的航程(改进版)(详细代码)
  8. 学渣的刷题之旅 leetcode刷题 9. 回文数
  9. 2021年危险化学品经营单位主要负责人免费试题及危险化学品经营单位主要负责人考试总结
  10. nisp学习-1.1信息安全与网络空间安全