Kreiranje animacije u web browser-u je omogu?eno preko API-ja definisanog specifikacijom Timing control for script-based animations.
Za animaciju je odgovoran metod requestAnimationFrame
(callback) gde je callback funkcija koja defini?e promene koje kreiraju animaciju.
U samoj callback funkciji se opet obi?no nalazi ponovni poziv funkcije requestAnimationFrame
.
Za zaustavljanje animacije se koristi metod cancelAnimationFrame
.
Za pozivanje callback funkcija se ?esto koriste funkcije setTimeout
i setInterval
.
Iako one omogu?avaju kontrolisane promene, sam browser (user agent) tako?e kontroli?e update rate animacije kako bi se optimizovali resursi.
Na primer, browser koji podr?ava pregled u tab-ovima uglavnom ne izvr?ava animaciju ako je ona u tab-u koji nije vidljiv.
Tako?e, zbog ovoga mo?e do?i i do kreiranja sporije ili br?e animacije koja ne?e prikazati ?eljeni rezultat.
U nastavku, za implementaciju animacije ?e biti iskori??en prethodni primer tako ?to ?e se za datu kocku uvesti animacija rotacije po y osi.
Prva razlika u odnosu na dosada?nje primere je ta da se funkcija drawElements
ne?e pozivati samo jednom ve? ?e se ovi pozivi
ponavljati na unapred zadati vremenski interval.
function tick() { window.requestAnimationFrame(tick); drawScene(); animate(); } function start() { var canvas = document.getElementById("canvas_s1"); initWebGL(canvas); initShaders(); initBuffers(); initTextures(); initMatrices(); tick(); }
Druga razlika je ta ?to ?e se matrica tranformacije sa svakim pozivom menjati kako bi se animirala rotacija i za promenu te vrednosti je potrebna funkcija animate()
.
var lastTime = 0; var rotateValue = 0; function animate() { var timeNow = new Date().getTime(); if (lastTime != 0) { var elapsed = timeNow - lastTime; rotateValue += (90 * elapsed) / 1000.0; rotateValue = (rotateValue % 360) * Math.PI / 180; } lastTime = timeNow; } function drawScene() { mat4.rotateY(mvMatrix, mvMatrix, rotateValue); ... }
Funkcija animate()
mo?e biti druga?ije definisana u zavisnosti od ?eljenog rezultata.
Ukoliko se pokrene ova aplikacija dobija se kocka koja se rotira, ali se pojavljuje problem sa osvetljenjem.
Da na sceni nema osvetljenja prethodni primer bi bio ispravan, me?utim, transformacija model-view matrice nije uticala na promenu matrice transformacije normala koja se koristi za postavku svetla.
Ovo zna?i da se prilikom savkog poziva iscrtavanja moraju ponovo rekreirati matrice. Jedino se matrica projekcija mo?e jednom postaviti po?to se ona poslednja primenjuje u shader-u i ne uti?e na osvetljenje.
Potrebne izmene su date u nastavku.
function initMatrices() { pMatrix = mat4.create(); mvMatrix = mat4.create(); normalMatrix = mat3.create(); mat4.perspective(pMatrix, Math.PI / 4, 400 / 400, 1, 10000.0); } function createMatrices() { mat4.identity(mvMatrix); mat4.translate(mvMatrix, mvMatrix, [0, 0, -10.0]); mat4.rotateY(mvMatrix, mvMatrix, rotateValue); mat4.rotateX(mvMatrix, mvMatrix, Math.PI / 6); normalMatrix = mat3.create(); mat3.normalFromMat4(normalMatrix, mvMatrix); } function drawScene() { createMatrices(); .... } function animate() { var timeNow = new Date().getTime(); if (lastTime != 0) { var elapsed = timeNow - lastTime; rotateFunction += 90 * elapsed / 1000.0; rotateValue = (rotateFunction % 360) * Math.PI / 180; } lastTime = timeNow; }
Uvedena je i mala promena u funkciji animate()
.
S obzirom da se svaki put kre?e od jedini?ne matrice mora se razdvojiti vrednost koja se akumulira i koja
predstavlja funkciju u odnosu na vreme od vrednosti koji odre?uje ugao rotacije. Rezultat ovakve promene je tra?ena animacija.
U ovom primeru nije bilo potrebe za uvo?enjem odlaganjem u?itavanja slike
s obzirom da se zbog same prirode implementacije animacija dobija potrebno odlaganje.
Ukoliko je potrebno odlo?iti po?etak animacije dok se resursi ne u?itaju (slika za teksturu) mo?e se uvesti funkcija koja odla?e po?etak (kao u prethodnom primeru
)
ili implementirati neki druga?iji koncept.