threejs water 模拟水动画

在这里插入图片描述在three.js中已经为我们封装好了这一效果,我们只需要引入特定的包就可以使用;

引入三个js包,它们相互关联,缺一不可,否则会报错,可在工程文件夹下example文件夹找到

    <script type="text/javascript" src="js/objects/Water2.js" ></script>//水的主要模型包
    <script type="text/javascript" src="js/objects/Reflector.js" ></script>//实现水的反射效果
    <script type="text/javascript" src="js/objects/Refractor.js" ></script>//实现水的折射效果

构造函数:
new THREE.Water(geometry,options)
-geometry:object,图形(一般使用平面PlaneGeometry图形)
-options:objects,
可选参数(颜色color,水波大小scale,流动方向flowDirection,画布宽度textureWidth,画布高度 textureHeight,流线图贴图flowMap等)
{

  • color:new THREE.Color(),

  • scale:number,

  • flowDirection:new THREE.Vector2(x,y),//二维方向向量

  • textureWidth:2的次方倍,

  • textureHeight:2的次方倍,

  • flowMap:map//流线贴图,


    }

注意,flowDiretion和flowMap两个属性不能连用,会起冲突;

有些朋友问shapeGeometry可以不?我的回答是可以,但是更推荐使用threejs内置的geometry,使用自定义形状是有效果的,但是不太明显,因为shapeGeomtry本身顶点过于复杂,Water包·运算较慢,水流效果较缓,尤其是浅色的,几乎看不到效果

效果例子查看地址

示例代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>测试water的属性</title>
		<script type="text/javascript" src="js/three.js" ></script>
		<script type="text/javascript" src="js/libs/stats.min.js" ></script>
		<script type="text/javascript" src="js/WebGL.js" ></script>
		<script type="text/javascript" src="js/libs/dat.gui.min.js" ></script>
		<script type="text/javascript" src="js/controls/OrbitControls.js" ></script>
		<script type="text/javascript" src="js/objects/Water2.js" ></script>
		<script type="text/javascript" src="js/objects/Reflector.js" ></script>
		<script type="text/javascript" src="js/objects/Refractor.js" ></script>
		<style>
			body{
				padding:0;
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<script>
			if(WEBGL.isWebGLAvailable()===false){alert("该浏览器不支持WebGL!");document.body.appendChild(WEBGL.getWebGLErrorMessage());}
		
			var scene,renderer,camera,controls,stats;
			var cubeTexture=new THREE.CubeTextureLoader().setPath("img/skybox1/").load([
				'px.jpg','nx.jpg',
				'py.jpg','ny.jpg',
				'pz.jpg','nz.jpg'
			]);//天空盒子
			function init(){
				scene=new THREE.Scene();
				scene.background=cubeTexture;
				
				renderer=new THREE.WebGLRenderer({
					antialias:true
				});
				renderer.setSize(window.innerWidth,window.innerHeight);
				renderer.setPixelRatio(window.devicePixelRatio);
				document.body.appendChild(renderer.domElement);
				
				camera=new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000);
				camera.position.set(0,30,0);
				camera.lookAt(scene.position);
				
				controls=new THREE.OrbitControls(camera,renderer.domElement);
				controls.enableDamping=true;
				controls.minDistance=0.1;
				controls.maxDistance=1000;
				
				stats=new Stats();
				document.body.appendChild(stats.dom);
				
				scene.add(new THREE.AmbientLight(0x404040));	
				var dLight=new THREE.DirectionalLight(0xffffff,0.8);
				dLight.position.set(-1,1,1);
				scene.add(dLight);
			}
			
			var axes;var torusKnot;
			var water1;var water2;var helper;
			function initModel(){
				axes=new THREE.AxesHelper(10);
				scene.add(axes);
				axes.visible=false;
				
				var geometry=new THREE.PlaneBufferGeometry(20,20,1);
				
				//平面1
				var plane=new THREE.Mesh(geometry,new THREE.MeshStandardMaterial({
					side:THREE.DoubleSide,
					roughness:0.8,
					metalness:0.4
				}));
				plane.position.set(-12,0,0);
				plane.rotation.x=-0.5*Math.PI;
				scene.add(plane);
				
				new THREE.TextureLoader().load("textures/hardwood2_diffuse.jpg",function(map){
					map.wrapS=map.wrapT=THREE.RepeatWrapping;
					map.anisotropy=16;
					map.repeat.set(4,4);
					plane.material.map=map;
					plane.material.needsUpdate=true;
				});
				
				torusKnot=new THREE.Mesh(new THREE.TorusKnotBufferGeometry(3,1,256,32),new THREE.MeshNormalMaterial());
				torusKnot.scale.set(0.5,0.5,0.5);
				torusKnot.position.set(-12,4,0);
				scene.add(torusKnot);
				
				//水1
				water1=new THREE.Water(geometry,{
					color:'#ffffff',
					scale:2,
					flowDirection:new THREE.Vector2(1,1),
					textureWidth:1024,
					textureHeight:1024,
				});
				water1.rotation.x=-0.5*Math.PI;
				water1.position.set(-12,1,0);
				scene.add(water1);
				
				//平面二
				var texture=new THREE.TextureLoader().load('textures/FloorsCheckerboard_S_Diffuse.jpg',function(map){
					map.wrapS=map.wrapT=THREE.RepeatWrapping;
					map.anisotropy=16;
					map.repeat.set(4,4);
				});						
				var ground=new THREE.Mesh(geometry,new THREE.MeshBasicMaterial({
					color:0xcccccc,
					map:texture
				}));
				ground.position.set(12,0,0);
				ground.rotation.x=-Math.PI/2;
				scene.add(ground);
				
				//水2
				var flowMap=new THREE.TextureLoader().load('textures/water/Water_1_M_Flow.jpg');
				water2=new THREE.Water(geometry,{
					scale:2,
					textureWidth:1024,
					textureHeiht:1024,
					flowMap:flowMap
				});
				water2.rotation.x=-Math.PI/2;
				water2.position.set(12,1,0);
				scene.add(water2);
				
				//贴图原图显示
				helper=new THREE.Mesh(geometry,new THREE.MeshBasicMaterial({
					map:flowMap
				}));
				helper.position.set(12,1.05,0);
				helper.rotation.x=-Math.PI/2;
				scene.add(helper);
				helper.visible=false;
			}
			
			var setting;
			function initGui(){
				setting={
					axesVisible:false,
					
					color:"#ffffff",
					scale:2,
					flowX:1,
					flowY:1,
					
					helper:false,
				}
				var gui=new dat.GUI();
				gui.add(setting,"axesVisible").onChange(function(e){
					axes.visible=e;
				});
				
				//水的属性设置
				var waterProperty=gui.addFolder("water1");
				waterProperty.addColor(setting,"color").onChange(function(e){
					water1.material.uniforms['color'].value.set(e);
				});
				waterProperty.add(setting,"scale",1,10).onChange(function(e){
					water1.material.uniforms['config'].value.w=e;
				});
				waterProperty.add(setting,"flowX",-1,1).onChange(function(e){
					water1.material.uniforms['flowDirection'].value.x=e;
					water1.material.uniforms['flowDirection'].value.normalize();//归一化
				});
				waterProperty.add(setting,"flowY",-1,1).onChange(function(e){
					water1.material.uniforms['flowDirection'].value.y=e;
					water1.material.uniforms['flowDirection'].value.normalize();
				});
								
				waterProperty.open();
				
				var waterPro2=gui.addFolder("water2");
				waterPro2.add(setting,"helper").name("show flowMap").onChange(function(e){
					helper.visible=e;
				});
				waterPro2.addColor(setting,"color").onChange(function(e){
					water2.material.uniforms['color'].value.set(e);
				});
				waterPro2.add(setting,"scale",1,10).onChange(function(e){
					water2.material.uniforms['config'].value.w=e;
				});
				waterPro2.open();
				
			}
			
			function onWindowResize(){
				camera.aspect=window.innerWidth/window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize(window.innerWidth,window.innerHeight);
			}
			
			var clock=new THREE.Clock();
			function render(){
				var delta=clock.getDelta();
				torusKnot.rotation.x+=delta;
				torusKnot.rotation.y+=delta*0.5;
				
				renderer.render(scene,camera);
			}
			
			function animate(){
				render();
				controls.update();
				stats.update();
				window.onresize=onWindowResize();
				requestAnimationFrame(animate);				
			}
			
			function threeStart(){
				init();
				initModel();
				initGui();
				animate();
			}
			threeStart();
		</script>
	</body>
</html>
  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值