Ovde ?e biti opisan postupak za osnove crtanja 3D objekata kroz najjednostavniji primer iscrtavanje kocke.
U ovom primeru se jo? uvek ne?e koristiti boje, teksture ili svetlo tako da rezultuju?a kocka jo? uvek ne?e izgledati realisti?no. U nastavku ?e biti opisani i ovi koncepti pa ?e i krajnji rezultat iscrtavanja biti bolji i intuitivniji.
Sli?no kao kod iscrtavanja kvadrata, potrebno je zadati temena kocke. Za koordinate temena je u primeru uzet slede?i niz.
var vertices = [ -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0 ];
Ovo je jedini?na kocka sa centrom u (0, 0). Ukoliko se zamisli da se gleda u kocku sa z-ose bez ikakvog ugla, za ?ta bi se moglo pojednostavljeno re?i da odgovara podrazumevanom stanju kad radimo sa WebGL-om, posmatra? bi video samo jedan kvadrat (prednju stranu).
Da bi se obezbedilo da kocka bude "vidljiva" odnosno da slika bude realisti?nija, kocku je potrebno malo rotirati (kamera), translirati u dubinu (da bi cela bila vidljiva) i za projekciju na 2D ravan je potrebno iskoristiti perspektivu (umesto ortogonalne projekcije koja je podrazumevana projekcija). Za sve ove operacije se koriste matrice transformacija i odgovaraju?e funkcije biblioteke glMatrix.
Pre po?etka rada, treba navesti jednu va?nu napomenu kada je rad sa matricama u pitanju. Mno?enje matrica nije komutativno tako da ukoliko se koristi vi?e transformacija redosled mno?enja matrica uti?e na kranji rezultat. Redosled operacija koji se naj?e??e koristi je:
M(projection) * M(scale) * M(rotation) * M(translation)*x
Implementacija vertex shader-a i definicija matrica su prikazani na slede?im listinzima.
<script id="shader-vertex" type="x-shader/x-vertex"> attribute vec3 vpos; uniform mat4 mvMatrix; uniform mat4 pMatrix; void main() { gl_Position = pMatrix * mvMatrix * vec4(vpos, 1); } </script>
function initMatrices() { pMatrix = mat4.create(); mat4.perspective(pMatrix, Math.PI/4, 400 / 400, 1, 10000.0); mvMatrix = mat4.create(); mat4.translate(mvMatrix, mvMatrix, [0, 0, -10.0]); mat4.rotateY(mvMatrix, mvMatrix, Math.PI/6); mat4.rotateX(mvMatrix, mvMatrix, Math.PI/6); }
Funkcije za matrice translacije i rotacije su jednostavne. U datom primeru kocka se translira za 10 ta?aka po z osi i rotira se po x i y osi za 30o.
Za postavljanje matrice perspektive se koriste ?etiri parametra.
{mat4} mat4.perspective(out, fovy, aspect, near, far)
Drugi parametar fovy
odre?uje ugao kojim se kreira vertikalan takozvani field of view,
tre?i parametar aspect
odre?uje takozvani aspect ratio, a poslednja dva parametra near
i far
odre?uju granice u kojima su objekti vidljivi.
Sada, kada su i vertexi i matrice definisani, postavlja se pitanje kako iscrtati kocku.
U primerima sa 2D objektima kori??ena je ?injenica da se kvadrat sastoji iz 2 trougla.
Redosledom navo?enja temena i izborom na?ina iscrtavanja (TRIANGLE_FAN
) obezbe?eno je da kona?na slika odgovara ?eljenoj.
Pokazano je da se prilikom promene nekih od ovih vrednosti dobijaju neo?ekivani rezultati.
S obzirom da se kocka sastoji iz 6 kvadrata i cela kocka se boji na isti na?in (sve stranice su iste boje i nije uvedno ni svetlo ni tekstura) mo?e se iskoristiti isti princip iscrtavanja.
Mo?e se ?est puta pozvati odgovaraju?a funkcija iscrtavanja paze?i pri tom na redosled temena u nizu. Ovo je legitiman na?in i mo?e se koristiti za dobijanje tra?enog rezultata
Me?utim, WebGL pored funkcije drawArrays
defini?e jo? jednu funkciju za iscrtavanje, a to je drawElements
.
U nastavku ?e se koristiti ova funkcija kako bi bila opisana s obzirom da ?e se ona koristiti za naredne primere.
void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset)
Umesto da se WebGL-u prosle?uje svaki vertex atribut vpos
, prosle?uje se niz ovih atributa koji se koriste za konstrukciju primitiva.
Odnosno, prilikom poziva drawArrays
funkcije bi se tri puta prosledila temena vertex-a kako bi se kreirao jedan trougao,
a kori??enjem funkcije drawElements
mogu?e je odjednom proslediti tri vertex vrednosti za koje ?e se iscrtati trougao.
Da bi se ova funkcija mogla koristiti, pored niza koji sadr?i podatke o vertex-ima, potrebno je krierati jo? jedan niz koji sadr?i podatke o tome kako su temena povezna sa trouglovima koji ?e se iscrtavati.
triangles = [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 6, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23 ];
Vrednosti u datom nizu ozna?avaju redni broj ?lana u nizu sa koordinatama. Prosle?ivanjem odre?ene trojke vrednosti iscrta?e se odgovaraju?i torugao.
Pre kona?nog iscrtavanja potrebno je prvo kreirati oba bafera.
var vBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); var tBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, tBuffer) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(triangles), gl.STATIC_DRAW);
Funkcija drawElements
koristi podatke iz bafera ELEMENT_ARRAY_BUFFER
,
sli?no kao ?to se vertexi nalaze u baferu ARRAY_BUFFER
.
Na kraju se poziva funkcija drawElements
.
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
U nastavku ?e biti navedena kratka poja?njenja osobina scene koje se koriste za kreiranje perspektive.
Slede?a lekcija