U primeru kvadrata je pokazano da se promenom boje u fragment shader-u postiže promena boje kvadrata.
gl_FragColor = vec4(0, 0, 1.0, 1.0);
Isto je moglo da se uradi i u prethodnom primeru gde se iscrtavala jednobojna kocka.
U nastavku će biti prikazano iscrtavanje kocke koja ima svih šest stranica različite boje.
Osnova promene u odnosu na prethodni primer je da je potrebno uvesti novi bafer koji sadrži podatke o bojama, zatim ga nekako povezati sa vertex-ima i u shader-ima iskoristiti za bojenje.
Bafer za boje će biti definisan na sledeći način.
colors = [ 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0 ];
U editoru su razdvojene grupe od po 4x4 vrednosti kako bi se uočilo da svaka grupa definiše bojenje jedne površine. Kao što se može primetiti sukcesivno se nalaze po četiri iste grupe vrednosti, odnosno četiri puta je ponovljena ista boja. Te četiri vrednosti odgovaraju verteksima jedne strane kocke i oni će biti obojeni u istu boju.
Poziv funkcije za kreiranje bafera je isti kao i za bafere koji odgovaraju vertex-ima i trouglovima koji se koriste za iscrtavanje.
cBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, cBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
Da bi se obezbedila generička vrednost boje koju fragment korist uvodi se nova vrsta promenljive.
varying vec4 vColor;
Varyng promenljve se globalne promenljive koje se koriste za prenos vrednosti iz vertex u fragment shader-e. Ukoliko i u jednom i drugom shader-u postoje promenljive istog imena deklarisane kao varying promenljive WebGL će povezati ove vrednosti.
Novi shader-i se kreiraju na na sledeći način.
<script id="shader-vertex" type="x-shader/x-vertex"> attribute vec4 aVertexColor; attribute vec3 aVertexPosition; uniform mat4 mvMatrix; uniform mat4 pMatrix; varying vec4 vColor; void main() { gl_Position = pMatrix * mvMatrix * vec4(aVertexPosition, 1); vColor = aVertexColor; } </script> <script id="shader-fragment" type="x-shader/x-fragment"> precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; } </script>
U fragment shader-u je neophodno definisati preciznost koja se koristi za postavku vrednosti deklarisanih kao float
ili integer
.
Iz specifikacije se vidi I da vertex shader ima postavljenu podrazumevanu preciznost za float vrednosti tako da deklaracija koja se pojavljuje u fragment shader-u nije neophodna i u vertex shader-u.
Poslednji korak je pozivanje funkcije drawScene
koja ovaj put ima zadatak da, pored vrednosti koje definišu vertex-e, prenese i vrednosti iz bafera sa bojama.
function drawScene() { var positionLocation = gl.getAttribLocation(shaderProgram, "aVertexPosition"); gl.enableVertexAttribArray(positionLocation); var colorLocation = gl.getAttribLocation(shaderProgram, "aVertexColor"); gl.enableVertexAttribArray(colorLocation); gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer); gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, cBuffer); gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, tBuffer); var sh_pMatrixUniform = gl.getUniformLocation(shaderProgram, "pMatrix"); var sh_mvMatrixUniform = gl.getUniformLocation(shaderProgram, "mvMatrix"); gl.uniformMatrix4fv(sh_pMatrixUniform, false, pMatrix); gl.uniformMatrix4fv(sh_mvMatrixUniform, false, mvMatrix); gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0); }
S obzirom da sei za boje kojom se iscrtavaju piskeli vrši interpolacija vrednosti slično kao što se vrši interpolacija za pozicije piksela, malim promenama u kodu se lako mogu dobiti gradijent efekti u ovoj aplikaciji.
Ako se promene boje dva vertex-a na jednoj stranici, u ovom primeru iz crvenog u crno, dobija se drugačiji rezultat.
colors = [ 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, .... ];
Iako je kreiran bafer sa bojama za svih šest stranica taj rezultat nije vidljiv u celosti i takav bafer nema puno smisla bez postojanja animacije (ili nekog vida transparencije). U nastavku će biti prikazano kako se koristi animacija u WebGL pa se taj postupak može primeniti i na ovu aplikaciju.