本例来源于官方案例

效果图

总体步骤

① 创建场景
② 创建相机
③ 创建物体
*** 创建顶点着色器
*** 创建片元着色器
④创建渲染器

html代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>html,body{padding: 0;margin: 0;overflow: hidden;}</style>
</head>
<body>
<div id="container"></div>
<script type="x-shader/x-vertex" id="vertexshader"></script>
<script type="x-shader/x-fragment" id="fragmentshader"></script>
<script type="module"></script>
</body>
</html>

导入文件,创建全局变量和函数

   import * as THREE from "./js/three.module.js";import {OrbitControls} from "./js/OrbitControls.js";import Stats from './js/stats.module.js';let renderer,scene,camera,spotLight,status,sprite,count=0;action();function action() {onload();run();}function onload(){}function run(){}function onResize(){}

①创建场景

onload函数中

        let container=document.getElementById("container");//获取containerscene=new THREE.Scene();//创建场景scene.fog = new THREE.FogExp2( 0x000000, 0.0008 );//设置雾

②创建相机

onload函数中

        camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,10000);camera.position.set(500,100,500);//创建相机并设置位置camera.lookAt(scene.position);

③创建物体

onload函数中

 let spriteGeometry=new THREE.BufferGeometry();let position=new Float32Array(50*50*3);//创建顶点存储空间let scales = new Float32Array( 50*50 );//创建存储尺寸的空间let i=0,j=0;for(let x=0;x<50;x++){//创建坐标点for(let y=0;y<50;y++){position[i]=x*100-((50*100)/2);//xposition[i+1]=0;//yposition[i+2]=y*100-((50*100)/2);//zscales[ j ] = 1;i+=3;j ++;}}spriteGeometry.addAttribute('position',new THREE.BufferAttribute(position,3));//把数据传入顶点着色器spriteGeometry.addAttribute('scale',new THREE.BufferAttribute(scales,1));//let spriteMaterial=new THREE.ShaderMaterial({//自定义着色器uniforms:{color: { value: new THREE.Color( 0x00CED1 ) },},vertexShader:document.getElementById("vertexshader").textContent,//顶点着色器属性vertexShader的属性值是顶点着色器代码字符串fragmentShader:document.getElementById("fragmentshader").textContent,//片元着色器属性fragmentShader的属性值是片元着色器代码字符串。});sprite=new THREE.Points(spriteGeometry,spriteMaterial);scene.add(sprite);

创建顶点着色器

<script type="x-shader/x-vertex" id="vertexshader">//使用ShaderMaterial类,顶点位置变量position无需声明,顶点着色器可以直接调用//modelViewMatrix:模型视图矩阵,内置变量//projectionMatrix:投影矩阵属性,内置变量attribute float scale;void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_PointSize = scale * ( 300.0 / - mvPosition.z );gl_Position = projectionMatrix * mvPosition;//第一行和本行代码的目的是坐标系转换。<投影矩阵>*<视图矩阵>*<模型矩阵>*<顶点坐标> 相乘的顺序不能改变}</script>

创建片元着色器

<script type="x-shader/x-fragment" id="fragmentshader">//gl_FragCoord:片元坐标,单位像素uniform vec3 color;void main() {if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;//不满足条件舍弃片元gl_FragColor = vec4( color, 1.0 );}</script>

注1:关于着色器提供的内置变量和属性这里推荐一篇博客着色器提供的内置变量和属性

注2:关于着色器中坐标转换这里有一篇博客推荐WebGL中模型矩阵、视图矩阵和投影矩阵

注3:关于片元着色器中discard这里也有一篇博客推荐WebGL着色器discard舍弃片元

④创建渲染器

onload函数中

renderer=new THREE.WebGLRenderer({antialias:true});renderer.setPixelRatio(window.devicePixelRatio);//renderer.shadowMap.enabled=true;//开启阴影renderer.gammaInput=true;renderer.gammaOutput=true;//inear转gamma//renderer.setClearColor(0XEEEEEE);//renderer.shadowMap.type=THREE.PCFSoftShadowMap;renderer.setSize(window.innerWidth,window.innerHeight);container.appendChild(renderer.domElement);status=new Stats();//创建频率显示container.appendChild(status.dom);//频率挂到左上角let contorl=new OrbitControls(camera,renderer.domElement);//添加鼠标滚动缩放,旋转对象window.addEventListener('resize',onResize,false);//浏览器大小改变监听

onResize函数中

function onResize() {camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);}

run函数中

function run() {requestAnimationFrame(run);let positions = sprite.geometry.attributes.position.array;let scales = sprite.geometry.attributes.scale.array;//BufferGeometry几何体对象具有.attributes属性,BufferGeometry.attributes具有顶点位置、顶点法向量、顶点uv坐标等属性,对应着色器中相应的attribute变量。let i = 0, j = 0;for ( let ix = 0; ix < 50; ix ++ ) {for ( let iy = 0; iy < 50; iy ++ ) {positions[ i + 1 ] = ( Math.sin( ( ix + count ) * 0.3 ) * 50 ) +( Math.sin( ( iy + count ) * 0.5 ) * 50 );//y轴上面呈现波浪形scales[ j ] = ( Math.sin( ( ix + count ) * 0.3 ) + 1 ) * 8 +( Math.sin( ( iy + count ) * 0.5 ) + 1 ) * 8;i += 3;j ++;}}sprite.geometry.attributes.position.needsUpdate = true;//通知顶点位置更新sprite.geometry.attributes.scale.needsUpdate = true;renderer.render(scene,camera);status.update();count += 0.1;}

总代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>html,body{padding: 0;margin: 0;overflow: hidden;}</style>
</head>
<body>
<div id="container"></div>
<script type="x-shader/x-vertex" id="vertexshader">//使用ShaderMaterial类,顶点位置变量position无需声明,顶点着色器可以直接调用//modelViewMatrix:模型视图矩阵,内置变量//projectionMatrix:投影矩阵属性,内置变量attribute float scale;void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_PointSize = scale * ( 300.0 / - mvPosition.z );gl_Position = projectionMatrix * mvPosition;//第一行和本行代码的目的是坐标系转换。<投影矩阵>*<视图矩阵>*<模型矩阵>*<顶点坐标> 相乘的顺序不能改变}</script>
<script type="x-shader/x-fragment" id="fragmentshader">//gl_FragCoord:片元坐标,单位像素uniform vec3 color;void main() {if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;//不满足条件舍弃片元gl_FragColor = vec4( color, 1.0 );}</script><script type="module">import * as THREE from "./js/three.module.js";import {OrbitControls} from "./js/OrbitControls.js";import Stats from './js/stats.module.js';let renderer,scene,camera,spotLight,status,sprite,count=0;action();function action() {onload();run();}function onload() {let container=document.getElementById("container");//获取containerscene=new THREE.Scene();//创建场景scene.fog = new THREE.FogExp2( 0x000000, 0.0008 );//设置雾camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,10000);camera.position.set(500,100,500);//创建相机并设置位置camera.lookAt(scene.position);//let axe=new THREE.AxesHelper(20);// scene.add(axe);//辅助工具,用于创建相机时,相机找到合适的位置//let ambientLight=new THREE.AmbientLight();//scene.add(ambientLight);/*spotLight=new THREE.SpotLight(0xffffff);spotLight.position.set(0, 5,20);spotLight.intensity=2;scene.add(spotLight);let spotLightMesh=new THREE.Mesh(new THREE.SphereGeometry(0.125,20,20),new THREE.MeshBasicMaterial());spotLight.add(spotLightMesh);*///let gridHelper=new THREE.GridHelper(30,20);//scene.add(gridHelper);let spriteGeometry=new THREE.BufferGeometry();let position=new Float32Array(50*50*3);//创建顶点存储空间let scales = new Float32Array( 50*50 );//创建存储尺寸的空间let i=0,j=0;for(let x=0;x<50;x++){for(let y=0;y<50;y++){position[i]=x*100-((50*100)/2);position[i+1]=0;//position[i+2]=y*100-((50*100)/2);scales[ j ] = 1;i+=3;j ++;}}spriteGeometry.addAttribute('position',new THREE.BufferAttribute(position,3));//把数据传入顶点着色器spriteGeometry.addAttribute('scale',new THREE.BufferAttribute(scales,1));//let spriteMaterial=new THREE.ShaderMaterial({//自定义着色器uniforms:{color: { value: new THREE.Color( 0x00CED1 ) },},vertexShader:document.getElementById("vertexshader").textContent,//顶点着色器属性vertexShader的属性值是顶点着色器代码字符串fragmentShader:document.getElementById("fragmentshader").textContent,//片元着色器属性fragmentShader的属性值是片元着色器代码字符串。});sprite=new THREE.Points(spriteGeometry,spriteMaterial);scene.add(sprite);renderer=new THREE.WebGLRenderer({antialias:true});renderer.setPixelRatio(window.devicePixelRatio);//renderer.shadowMap.enabled=true;//开启阴影renderer.gammaInput=true;renderer.gammaOutput=true;//inear转gamma//renderer.setClearColor(0XEEEEEE);//renderer.shadowMap.type=THREE.PCFSoftShadowMap;renderer.setSize(window.innerWidth,window.innerHeight);container.appendChild(renderer.domElement);status=new Stats();//创建频率显示container.appendChild(status.dom);//频率挂到左上角let contorl=new OrbitControls(camera,renderer.domElement);//添加鼠标滚动缩放,旋转对象window.addEventListener('resize',onResize,false);//浏览器大小改变监听}function onResize() {camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);}function run() {requestAnimationFrame(run);let positions = sprite.geometry.attributes.position.array;let scales = sprite.geometry.attributes.scale.array;//BufferGeometry几何体对象具有.attributes属性,BufferGeometry.attributes具有顶点位置、顶点法向量、顶点uv坐标等属性,对应着色器中相应的attribute变量。let i = 0, j = 0;for ( let ix = 0; ix < 50; ix ++ ) {for ( let iy = 0; iy < 50; iy ++ ) {positions[ i + 1 ] = ( Math.sin( ( ix + count ) * 0.3 ) * 50 ) +( Math.sin( ( iy + count ) * 0.5 ) * 50 );//y轴上面呈现波浪形scales[ j ] = ( Math.sin( ( ix + count ) * 0.3 ) + 1 ) * 8 +( Math.sin( ( iy + count ) * 0.5 ) + 1 ) * 8;i += 3;j ++;}}sprite.geometry.attributes.position.needsUpdate = true;//通知顶点位置更新sprite.geometry.attributes.scale.needsUpdate = true;renderer.render(scene,camera);status.update();count += 0.1;}</script>
</body>
</html>

threeJS创建粒子波浪相关推荐

  1. css和js3d粒子,升级版ThreeJS 3D粒子波浪动画

    升级版ThreeJS 3D粒子波浪动画 2020-04-12 23:07:22 1307 编程开发 效果图 升级版demo 2:改变粒子的形状 demo 2 升级版demo 1:改变粒子大小,颜色 d ...

  2. H5实例教学--ThreeJs 实现粒子动画飘花效果

    粒子动画在ThreeJs可以用几种方式实现 本次样例使用Sprite类来构建粒子 官方对Sprite类的解释 Sprite A sprite is a plane that always faces ...

  3. html 页面飘花,HTML5开发实例-ThreeJs实现粒子动画飘花效果代码分享

    粒子动画在ThreeJs可以用几种方式实现 本次样例使用Sprite类来构建粒子 大概意思:这个类创建的对象是一个始终面向相机的平面,可以把贴图应用在上面,Sprite对象无法添加阴影 ,所以cast ...

  4. HTML做3D立体特效,html5 3D立体粒子波浪动画特效代码

    特效描述:html5 3D立体 粒子波浪动画.3D 粒子动画特效 代码结构 1. 引入JS 2. HTML代码 /// Scene const sceneSettings = { width: () ...

  5. Unity 游戏开发技巧集锦之使用忍者飞镖创建粒子效果

    Unity 游戏开发技巧集锦之使用忍者飞镖创建粒子效果 使用忍者飞镖创建粒子效果 游戏中,诸如烟.火.水滴.落叶等粒子效果,都可以使用粒子系统(particle system)来实现.例如,<明 ...

  6. threejs创建平面几何形状

    创建平面几何形状 平面几何形状有三种:点,线,面三种,下面说说用threejs创建这几种形状的方法. 创建点 创建点可以使用Points类. function createPoints(){//创建一 ...

  7. html5仿腾讯,高仿腾讯QQ Xplan(X计划)的H5页面(1):threejs创建地球

    上个月底,在朋友圈看到一个号称"这可能是地球上最美的h5"的分享,点进入后发现这个h5还很别致,思考了一会,决定要不高仿一个? 到今天为止,高仿基本完成, 除了手机端的media控 ...

  8. html5波浪效果,html5 canvas粒子波浪动画特效

    特效描述:html5 canvas 粒子波浪动画特效.html5基于canvas绘制波涛汹涌的粒子波浪动画. 代码结构 1. HTML代码 'use strict'; var FastRandom = ...

  9. threejs 绘制球体_实战:用 threejs 创建一个地球

    原标题:实战:用 threejs 创建一个地球 提示: 讲座 前端大型免费公开课讲座 教程 从零基础学前端教程,都在这~ 上个月底,在朋友圈看到一个号称"这可能是地球上最美的h5" ...

最新文章

  1. html 列表bootstrap,bootstrap都有哪些类?
  2. 【 FPGA 】FIR 滤波器结构和优化(二)之系数填充(Coefficient Padding)
  3. 设置在本文件里查找_Win 10 自带聚焦搜索?这么设置轻松查找电脑文件
  4. --- struts数据源配置(详解)---
  5. 给GridView设置行高
  6. 使用禅道Docker安装包安装
  7. root用户连接mysql数据库出错 1045 access denied for user 'root'@'localhost' using password yes
  8. 学习进度表(160519更新)
  9. 史上最强Android 开启照相或者是从本地相册选中一张图片以后先裁剪在保存并显示的讲解附源码...
  10. 3137102432_施少兵_实验2
  11. AR人体姿态识别,实现无边界的人机交互
  12. PHPWAMP开启SSL,PHPWAMP配置ssl证书
  13. 如何使用群发工具?邮件群发软件免费有哪些?
  14. mysql基础命令语句以及使用方法:
  15. SA299学习笔记 第一章 描述接口配置(3)
  16. win10系统的应用商店不见了怎么安装回来
  17. VBA 读写文本文件
  18. 杰理之使用MIC隔电容方案,微信语音前几秒也出现“哒哒”【篇】
  19. 【老九学堂】【C++】位运算符
  20. 【转】linux服务器的Gzip文件压缩方法

热门文章

  1. 等保培训.04.主机系统安全测评
  2. 告诉大家操作系统32位和64位的区别
  3. 中国古人记录的奇妙客星
  4. NLP文本情感分析:测试集loss比训练集loss大很多,训练集效果好测试集效果差的原因
  5. 达梦数据库迁移数据报错 字符串截断
  6. 3dmax 基本选择工具的使用
  7. Linux系统checkra1n装错插件,CheckRa1n越狱常见问题汇总 CheckRa1n越狱问题解决方法
  8. 20级网络学生---循环
  9. 纷享销客高燕:回归第一性原理,B2B企业如何向精益化要增长
  10. CleanMyMac X是干嘛的?及最新版功能介绍