WebGL로 액체 효과를 만드는 방법

액체 효과 크리에이티브 블로그 로고

많은 웹 디자이너는 사용자의 관심을 끌 수 있도록 사이트 디자인에 큰 영향을 줄 수있는 방법을 찾습니다. 헤더 그래픽을 사용하는 것에서 시작 페이지 메뉴 아래에 슬라이드 쇼를 배치하는 것, 전체 브라우저 너비가되는 방법에 이르기까지 방법은 수년에 걸쳐 발전해 왔으며 이제 대부분의 사이트가 동일한 형식을 따르고 있습니다. 웹 사이트 빌더 ).

오늘날, 다른 웹 어워드 사이트에서 '오늘의 사이트'를 수상한 디자인은 일반적으로 조금 더 독특한 것을 시도하고 수행하며 WebGL은 이에 적합합니다. 인터랙티브 요소를 추가하면 사용자의 관심을 끌 수 있고 방금 방문한 다른 사이트와 동일하지 않다는 것을 보여줄 수 있습니다. 그것은 단지 거대한 슬라이드 쇼와 일부를 갖는 것보다 훨씬 더 흥미로운 사이트를 만듭니다. 시차 스크롤 . 복잡한 요구 사항이있는 사이트가있는 경우 웹 호스팅 서비스가 정점에 있습니다.

이 튜토리얼에서 스플래시 효과를 만들기 위해 액체의 반사 표면이 추가되고, 이것은 앞으로 움직이는 파도와 함께 카메라를 향해 애니메이션됩니다. 모양과 느낌을 완성하기 위해 앞으로 나아가는 입자도있을 것입니다. 중앙에는 사이트의 로고가 있고 전체 장면이 사용자의 마우스 움직임에 반응하여 콘텐츠가 이동하고 3D가 실제로 돋보이게합니다.



그만큼 로고 디자인 투명 PNG로 렌더링됩니다 (안전하게 클라우드 스토리지 ), 따라서 자신의 디자인에 쉽게 맞춤 설정할 수 있습니다. 조명은 또한 색상이 주위를 돌고 장면 내에서 다른 파도를 강조하도록 애니메이션됩니다.

파일 다운로드 이 튜토리얼을 위해.

01. 초기 변수 추가

프로젝트 파일에서 시작 폴더를 열고이를 코드 편집기로 끕니다. 열다 ' index.html '그러면 JavaScript 라이브러리가 이미 연결되어있는 것을 볼 수 있습니다. 빈 스크립트 태그 안에 코드가 들어갑니다. 여기서 WebGL이 감지되어 프로젝트가 실행될 수 있는지 확인한 다음 장면에서 사용할 전체 범위의 변수가 추가됩니다.

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. 더 많은 변수 생성

다음 변수 블록은 물 바닥의 크기와 초기 마우스 위치와 함께 이동하는 속도를 처리합니다. 화면의 중앙 부분을 다듬고 개선 된 노이즈 라이브러리를 사용하여 수면을 만듭니다.

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. 마우스 계산

장면의 후 처리 효과를 위해 몇 가지 최종 변수가 추가됩니다. 마우스 움직임을 확인하는 이벤트 리스너가 추가됩니다. 장면은 마우스 움직임에 반응하기 위해 디스플레이 포트에서 움직일 것입니다. 여기에 추가 된 기능은 허용되는 이동량을 계산합니다.

어도비 캐릭터 애니메이터를 얻는 방법

04. 후 처리 설정 변경

' 매개 변수 '기능은 후 처리 효과에 대한 모든 설정이 저장되는 곳입니다. 변경해야 할 사항이 있으면 여기에서 변경할 수 있습니다. 틸트 시프트 블러는 처음 네 줄에서 가려진 다음 필름이 나머지 줄로 전달됩니다. 이것은 주로 화면 강도와 노이즈 강도에 대한 것입니다.

05. 최종 매개 변수 설정

마지막 매개 변수는 화면 가장자리 주변의 어두운 비 네트 용입니다. ' 초기화 '및' 생기 있는 '함수가 실행되도록 호출됩니다. ' 생기 있는 '함수는 자습서의 후반부에 생성되지만' 초기화 '함수가 여기에 생성됩니다. 카메라와 장면은 3D 콘텐츠를 볼 수 있도록 설정됩니다.

effectVignette.uniforms['offset'].value = 1.0; effectVignette.uniforms['darkness'].value = 1.3; } init(); animate(); 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. 불이 들어 오게

장면의 내용을보기 위해 4 개의 조명이 배치됩니다. 첫 번째는 반구 조명으로, 장면의 기본 분위기를 얻기 위해 사용됩니다. 다음은 장면 중간에 밝은 파란색 빛을 추가하는 중앙 조명입니다. 이것은 전체 장면에 약간의 빛을주기 위해 한쪽으로 설정됩니다.

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. 애니메이션 조명

추가 할 다음 두 개의 조명입니다. ' 포인트 라이트 '및' PointLight2 '는 장면 주변에서 반대 방향으로 원을 그리는 컬러 조명으로, 뷰에서 조명이 지속적으로 변경됩니다. 첫 번째는 분홍색 빛이고 두 번째는 주황색 빛입니다. 반사 이미지의 경로와 형식은 마지막 두 줄에 설정됩니다.

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';

08. 반짝이는 표면

액체 표면은 반사되고 반짝이는 표면을 가지며 이는 반사 큐브를 생성하여 수행됩니다. 이것은 내부에 360도 스카이 박스가 배치 된 큐브로, 액체 표면에 반사됩니다. ' URL '배열에는로드 할 이미지가 포함 된 다음 재료가 설정됩니다.

09. 일부 그룹 설정

무버 그룹에는 나중에 추가 될 일부 입자가 포함되고 바닥 그룹에는 액체 표면이 포함됩니다. 해당 표면을 유지할 새 3D 개체가 생성됩니다. 두 개의 액체 표면이 있습니다. 하나는 반사 재료를, 두 번째는 와이어 프레임을 가질 것입니다. 바닥재 ', 여기에 정의 된대로.

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

10. 표면 만들기

액체 효과 만들기 : 표면 만들기

첫 번째 액체 표면이 추가되면 여기에 반사 맵이 매우 분명하고 안개는 배경과 표면을 함께 혼합하는 데 도움이됩니다.

여기서 두 개의 액체 표면은 ' floorMesh '및' floorMesh2 '. 그들은 ' floorGroup '그런 다음 카메라 앞에서 좋은 시야각으로 회전했습니다. 이것은 직접적으로 평평하지는 않지만 더 좋아 보이기 때문에 약간 각도가 있습니다.

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. 부유 입자 추가

액체 효과 만들기 : 떠 다니는 입자 추가

플로팅 파티클이 장면을 채우고이 모든 것이 렌더 기능에서 애니메이션 될 때 카메라를 향해 움직이는 느낌을줍니다.

여기에있는 코드 섹션은 빈 지오메트리 오브젝트를 만든 다음 여기에 입자 역할을하는 2,000 개의 정점을 배치합니다. 이들은 X, Y 및 Z 축의 임의 위치에 배포됩니다. 이들은 액체 바닥의 표면 바로 위에 떠 있습니다.

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(vertex); }

12. 룩 만들기

여기에 정의 된 재질은 입자의 모양을 설정합니다. 이전 단계에서로드 된 이미지는 재질이 생성되면 각 입자의 이미지로 사용됩니다. 그런 다음 모든 입자에 대한 형상의 각 지점에 적용됩니다. 그런 다음 장면에 추가됩니다.

액체 효과 만들기 : 로고 추가

투명한 PNG 이미지 인 로고를 추가하면 장면 중앙에 배치되며 나중에 자신의 로고로 쉽게 교체 할 수 있습니다.

로고가 화면 중앙에 배치되고 카메라를 향하는 평면에 추가됩니다. 로고는 약간 투명하게 만들어졌으며 더 밝은 물체가 지나갈 때 더 잘 보이도록 추가 블렌드가 제공됩니다. 이것은 배치되고 장면에 배치됩니다.

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

14. 렌더링 설정 추가

렌더러는 부드럽고 앤티 앨리어싱 된 가장자리를 갖도록 설정되었으며 이제 배경색이 설정되었습니다. 장면이 HTML 페이지에 있도록 문서 본문에 추가됩니다. 후 처리 효과는 다양한 렌더 및 셰이더 패스를 초기화하여 설정됩니다.

15. 패스 만들기

필름과 글리치 패스가 추가되면 모든 패스를 함께 구성하는 효과 컴포저가 생성됩니다. 이것들은 작곡가에 하나씩 추가되며 결국 청중을 위해 화면에 렌더링됩니다.

16. 'init'기능 닫기

장면 초기화를 위해 마지막 몇 가지 설정이 추가됩니다. 사후 처리를위한 매개 변수가 설정되고 웨이브 설정이 호출되며 브라우저 크기가 조정될 때마다 이벤트 리스너가 추가됩니다. 이렇게하면 새 치수에 맞게 디스플레이를 업데이트 할 수 있습니다.

17. 웨이브 설정

이제 액체 표면에 대한 파도가 생성됩니다. 이것은 x 및 z 축에서 바닥 지오메트리의 각 정점을 통해 이동하고 y 축에서 위쪽으로 이동하여 수행됩니다. 이 단계에서 ' ...에 대한 '루프는 x 및 z 축에 대해 생성됩니다.

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;

18. 파도 만들기

모든 정점이 같은 방식으로 위쪽으로 확장되는 것은 아닙니다. 카메라에서 가장 먼 쪽이 커지고 측면이 약간 줄어들고 카메라에 가장 가까운 쪽이 가장 적게 조정됩니다. 이렇게하면 뒷면과 측면이 약간 더 흥미롭게 보입니다.

if ((i > 30) || (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. 크기 조정 및 애니메이션

창의 크기가 조정되면 여기에있는 함수가 16 단계에서 설정 한 리스너에서 호출됩니다. 카메라, 렌더러 및 작곡가는 브라우저 창의 새 크기와 일치하도록 여기에서 모두 재설정됩니다. animate 함수는 디스플레이를 업데이트하기 위해 render 함수를 호출하여 60fps로 설정됩니다.

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); render(); }

20. 행동의 모든 프레임을 설정

렌더링 함수는 모든 프레임에서 호출됩니다. 포인트 라이트는 장면에서 궤도를 돌도록 설정되고 카메라는 마우스 움직임에 따라 배치되며 약간의 여유가있어 점차 제자리로 이동합니다. 카메라는 항상 장면의 중심을 보도록 설정되어 있습니다.

function render() { var timer = -0.0002 * Date.now(); pointLight.position.x = 2400 * Math.cos(timer); pointLight.position.z = 2400 * Math.sin(timer); 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. 장면 렌더링

액체 효과 만들기 : 장면 렌더링

종종 포스트 프로세싱 효과 중 하나가 화면에 글리치 효과를 실행하여 정상으로 돌아 가기 전에 화면을 활기차게 만들고 왜곡합니다.

수상 경력에 빛나는 웹 디자이너 컨퍼런스 Generate가 4 월 24 일부터 25 일까지 NYC로 돌아옵니다! 티켓을 예약하려면 www.generateconf.com을 방문하십시오.

수상 경력에 빛나는 웹 디자이너 컨퍼런스 Generate가 4 월 24 일부터 25 일까지 NYC로 돌아옵니다! 티켓을 예약하려면 www.generateconf.com

마지막 단계에서 입자는 개별 정점에서 앞으로 이동하고 카메라에 도달하면 거리에 다시 배치됩니다. 이것은 업데이트되고 ' setWaves ' 함수가 호출되어 파도가 앞으로 나아갑니다. 장면은 효과 작곡가에 의해 렌더링됩니다.

이 기사는 원래 크리에이티브 웹 디자인 잡지에 게재되었습니다. 웹 디자이너 . 여기에서 Web Designer 구독 .

관련 기사: