Liquid effect Creative Bloq logo

+$Many web designers look for ways to add a big impact to their site designs, so that they'll grab the attention of their users. Methods have evolved over the years, from using a header graphic, to placing a slideshow under the landing page menu, to becoming full browser width – and now the vast majority of sites follow this same format.

+$Today, the designs that win 'site of the day' on different web awards sites generally try and do something that's a little more unique, and WebGL is great for this. Adding an interactive element can really grab users' attention and show that this isn't the same as the other sites they've just visited. It makes a site much more interesting than just having a giant slideshow and some视差滚动

+$To make a splash effect in this tutorial, a liquid, reflective surface will be added, and this will be animated towards the camera with rolling waves moving forward. There will also be particles that move forward to complete the look and feel. In the centre will be the site's logo, and the whole scene will react to the user's mouse movement so that the content shifts and makes the 3D really stand out.



+$01. Add Initial Variables

+$Open the start folder from the project files and drag this into your code editor. Open '的index.html+$' and you will see that the JavaScript libraries have already been linked up for you. Inside the empty script tags is where the code will go. Here WebGL is detected to make sure the project can be run, then a whole range of variables are added that will be used in the scene.

if(!Detector.webgl)Detector.addGetWebGLMessage(); var SCREEN_WIDTH = window.innerWidth; var SCREEN_HEIGHT = window.innerHeight; var renderer,camera,scene,moverGroup,floorGeometry,floorMaterial,pointLight,pointLight2,pGeometry; var FLOOR_RES = 60; var FLOOR_HT = 650; var stepCount = 0; var noiseScale = 9.5; var noiseSeed = Math.random()* 100;

+$02. Create More Variables


var FLOOR_WIDTH = 3600; var FLOOR_DEPTH = 4800; var MOVE_SPD = 1.9; var mouseX = 0; var mouseY = 0; var windowHalfX = window.innerWidth / 2; var windowHalfY = window.innerHeight / 2; var snoise = new ImprovedNoise(); var textureLoader = new THREE.TextureLoader();

+$03. Calculate The Mouse


+$04. Change post processing settings

+$The 'PARAMS+$' function is where all the settings for the post processing effects will be stored. If you need to change anything, this is the place to do it. The tilt shift blur is covered in the first four lines, then the film pass in the remaining lines. This is mainly for the screen intensity and noise intensity.

+$05. Set Final Parameters

+$The last of the parameters is for the dark vignette around the edge of the screen. The '在里面'和'+$animate+$' functions are called to run. The '+$animate+$' function will be created much later in the tutorial, but the '在里面+$' function is created here. The camera and scene are set up to allow viewing of the 3D content.

effectVignette.uniforms [“offset”]。value = 1.0; effectVignette.uniforms [“darkness”]。value = 1.3; } 在里面();动画(); function init(){camera = new THREE.PerspectiveCamera(70,window.innerWidth / window.innerHeight,1,4000); camera.position.z = 2750; scene = new THREE.Scene(); scene.fog = new THREE.FogExp2(0x1c3c4a,0.00045);

+$06. Let the light in


var hemisphereLight = new THREE.HemisphereLight(0xe3feff,0xe6ddc8,0.7); scene.add(hemisphereLight); hemisphereLight.position.y = 300; var centerLight = new THREE.SpotLight(0xb7f9ff,1); scene.add(centerLight); centerLight.position.set(2500,300,2000); centerLight.penumbra = 1; centerLight.decay = 5;

+$07. Animate Lights

+$The next two lights to be added. '+$PointLight'和'+$PointLight2+$' are coloured lights that will circle in opposite directions around the scene so that the light changes constantly in the view. The first is a pink light and the second is an orange light. The path and format for the reflection images are set in the last two lines.

pointLight = new THREE.PointLight(0xe07bff,1.5); pointLight.position.z = 200; scene.add(POINTLIGHT); pointLight2 = new THREE.PointLight(0xff4e00,1.2); pointLight2.position.z = 200; scene.add(pointLight2); var path =“img /”; var format ='.jpg';


+$The liquid surface will have a reflective, shiny surface and this is done by creating a reflection cube. This is a cube with a 360-degree skybox placed inside it, which will be reflected onto the surface of the liquid. The '+$urls+$' array contains the images to be loaded, then the material is set up.

+$09. Set up some groups

+$The mover group will contain some particles that will be added later, while the floor group will contain the surface of the liquid. A new 3D object is created that will hold that surface. There will be two liquid surfaces; one will have the reflective material and the second will have the wireframe '+$floorMaterial+$', as defined here.

moverGroup = new THREE.Object3D(); scene.add(moverGroup); var floorGroup = new THREE.Object3D(); var floorMaterial = new THREE.MeshPhongMaterial({color:0xeeeeee,side:THREE.DoubleSide,blend:THREE.AdditiveBlending,wireframe:true}); floorGeometry = new THREE.PlaneGeometry(FLOOR_WIDTH + 1200,FLOOR_DEPTH,FLOOR_RES,FLOOR_RES);

+$10. Make The Surfaces

Create liquid effects: make the surface


+$The two liquid surfaces are created here as '+$floorMesh'和'+$floorMesh2+$'. They are positioned and placed inside the '+$floorGroup+$' then rotated to a good viewing angle in front of the camera. This isn't directly flat, but slightly angled as it looks better like that.

var floorMesh = new THREE.Mesh(floorGeometry,cubeMaterial); var floorMesh2 = new THREE.Mesh(floorGeometry,floorMaterial); floorMesh2.position.y = 20; floorMesh2.position.z = 5; floorGroup.add(floorMesh); floorGroup.add(floorMesh2); scene.add(floorGroup); floorMesh.rotation.x = Math.PI / 1.65; floorMesh2.rotation.x = Math.PI / 1.65; floorGroup.position.y = 180;

+$11. Add Floating Particles

Create liquid effects: add floating particles



pGeometry = new THREE.Geometry(); sprite = textureLoader.load(“img / sprite.png”); for(i = 0; i <2000; i ++){var vertex = new THREE.Vector3(); vertex.x = 4000 * Math.random() -  2000; vertex.y = -200 + Math.random()* 700; vertex.z = 5000 * Math.random() -  2000; pGeometry.vertices.push(顶点); }

+$12. Create The Look


Create liquid effects: add the logo



sprite = textureLoader.load(“img / logo.png”); geometry = new THREE.PlaneBufferGeometry(500,640,1); material = new THREE.MeshLambertMaterial({transparent:true,opacity:0.8,blend:THREE.AdditiveBlending,map:sprite,side:THREE.DoubleSide}); var plane = new THREE.Mesh(geometry,material); plane.position.set(0,70,1800); scene.add(平面);

+$14. Add the render settings


+$15. Make The Pass


+$16. Close the 'init' function


+$17. Set up the waves

+$The waves are created now for the surface of the liquid. This is done by moving through each vertex of the floor geometry on the x and z axis and moving it upward on the y axis. At this stage the '对于+$' loops are created for the x and z axis.

function setWaves(){stepCount ++; moverGroup.position.z = -MOVE_SPD; var i,ipos; var offset = stepCount * MOVE_SPD / FLOOR_DEPTH * FLOOR_RES; for(i = 0; i <FLOOR_RES + 1; i ++){for(var j = 0; j <FLOOR_RES + 1; j ++){ipos = i + offset;



if((i> 30)||(j <12)||(j> 48)){floorGeometry.vertices [i *(FLOOR_RES + 1)+ j] .z = snoise.noise(ipos / FLOOR_RES * noiseScale, j / FLOOR_RES * noiseScale,noiseSeed)* FLOOR_HT; } else if(i> 25 && i <30){floorGeometry.vertices [i *(FLOOR_RES + 1)+ j] .z = snoise.noise(ipos / FLOOR_RES * noiseScale,j / FLOOR_RES * noiseScale,noiseSeed)*( FLOOR_HT / 1.2); } else {floorGeometry.vertices [i *(FLOOR_RES + 1)+ j] .z = snoise.noise(ipos / FLOOR_RES * noiseScale,j / FLOOR_RES * noiseScale,noiseSeed)*(FLOOR_HT / 2); floorGeometry.verticesNeedUpdate = true; }

+$19. Resize And Animate

调整窗口大小时,此处的函数将从步骤16中设置的侦听器调用。摄像机,渲染器和编辑器都在此处重置,以匹配浏览器窗口的新维度。 Animate函数只将其自身设置为60fps,调用render函数来更新显示。

function onWindowResize(){camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth,window.innerHeight); composer.setSize(window.innerWidth,window.innerHeight); function animate(){requestAnimationFrame(animate);渲染(); }

+$20. Set every frame of action


function render(){var timer = -0.0002 * Date.now(); pointLight.position.x = 2400 * Math.cos(计时器); pointLight.position.z = 2400 * Math.sin(计时器); pointLight2.position.x = 1800 * Math.cos(-timer * 1.5); pointLight2.position.z = 1800 * Math.sin(-timer * 1.5); camera.position.x + =(mouseX  -  camera.position.x)* .05; camera.position.y + =(-mouseY  -  camera.position.y)* .05; camera.lookAt(scene.position);

+$21. Render The Scene

Create liquid effect: render the scene


Generate, the award winning conference for web designers, returns to NYC on April 24-25! To book tickets visit www.generateconf.com&nbsp;

+$In the final step the particles are moved forward on their individual vertex, and if they get to the camera, they are placed back into the distance. This is updated and the '+$setWaves'+$function is called to make the waves roll forward. The scene is rendered by the effects composer.

本文最初发表于创意网页设计杂志网页设计者在此订阅Web Designer