Historie: Web & 3D
						Snaha dostat 3D do webového prohlížeče není nová.
						
							- VRML: značkovací jazyk založený na XML
								- Nutné instalovat do prohlížeče dodatečný plugin
- Většinou pouze procházení statické scény
- Blender Player: interaktivní aplikace (hry)
								- Nutné instalovat do prohlížeče dodatečný plugin
- Plně interaktivní aplikace skriptovatelné v Pythonu
- Obsah nutné vytvářet v jedné aplikaci
- Flash: snad ani není nutné komentovat
Důvody neúspěchu?
						
							- Nutné použít plugin
- Paměťové náročné
- Špatný návrh
Podpora ve webových prohlížečích
						V současnosti (2016) podporují WebGL 1.0.4 všechny hlavní prohlížeče (jejich poslední verze). Statisticky 92% uživatelů má zapnutou podporu WebGL. Aktuální statistika je dostupná na webglstats.com (průkaznost statistických dat?).
						Podpora pro WebGL 2.0 (založeno na OpenGL ES 3.0) je experimentálně dostupná pouze v některých prohlížečích a musí být explicitně povolená.
					
					
						Důvod nefunkčnosti WebGL
						
							- Stará verze prohlížeče.
- Neaktualizovaný a nebezpečný ovladač grafické karty (blacklisting).
- Vypnutá podpora WebGL v nastavení prohlížeče.
Khronos Conformance testy
						Khronos Group vytvořil sadu testů podobných ACID testům od W3C. Svůj prohlížeč si můžete otestovat na adrese:
						https://goo.gl/LMJfC6
					
				
				
					
						Canvas & Javascript & WebGL
						
							- Nutná je nejprve podpora por HTML5 elelement canvas
- Následně je nezbytné, aby Javascript API mělo přístup k 3D kontextu canvasu ("webgl"/"experimental-webgl")
Minimální WebGL aplikace
<!DOCTYPE html>
<html><body>
<canvas id="c01"></canvas>
<script type="text/javascript">
	var canvas = document.getElementById("c01");
	var gl = canvas.getContext("webgl");
	gl.clearColor(0.3, 0.8, 0.3, 1.0);
	gl.clear(gl.COLOR_BUFFER_BIT);
</script>
</body></html>
					
				
				
					Zobrazovací řetězec WebGL
					
						- WebGL nepoužívá pevně danou zobrazovací řetězec jako má OpenGL (viz. předchozí přednáška)
- WebGL vyžaduje použití vertex a fragment shaderů
 
				
				
					
						Vertex & Fragment Shader
						
							- Speciální programovací jazyk podobný jazyku C
- Kompilovaný na grafické kartě
- Vykonávaný na grafické kartě
- Grafická karta (2016): masivně paralelní stroj (stovky až tisíce výpočetních jader) - velmi rychlý běh
Vertex Shader
						
							- Každý vrchol vstupující do vertex shaderu je tímto shaderem transformován. Zde mohou být prováděny například tyto operace:
								- Transformace (rotace, zvětšní, posun, atd.)
- Transformace do souř. systému kamery
- Promítání (perspektivní/roviné)
- Mnohé další
- Výstupem je čtyřprvkový vektor gl_Position, velikost bodugl_PointSizea případně nastavení hodnot pro proměnné typu varying.
Minimální Vertex Shader
<!DOCTYPE html>
<html><body>
<canvas id="c02"></canvas>
<script type="text/javascript">
	var canvas = document.getElementById("c02");
	var gl = canvas.getContext("webgl");
	var vertexShader = gl.createShader(gl.VERTEX_SHADER);
	gl.shaderSource(vertexShader,
		'void main(void) { gl_Position = vec4(0, 0, 0, 1);}');
	gl.compileShader(vertexShader);
	var program = gl.createProgram();
	gl.attachShader(program, vertexShader);
	gl.linkProgram(program); gl.useProgram(program);
	gl.clearColor(0.3, 0.3, 0.8, 1.0);
	gl.clear(gl.COLOR_BUFFER_BIT);
</script>
</body></html>
					
					
						Příklad minimálního Vertex Shaderu
					Demonstrační program má drobnou nevýhodu: vertex shader nic nedělá, protože nemá žádná vstupní data a jeho výstup není vstupem do fragment shaderu.
					
					
						Tvorba primitiv a rasterizace
						
							- Po transformaci vertexů dojde k vytvoření jednotlivých primitiv (základních elementů):
- Následně dojde k rasterizaci těchto základních elementů do rastru fragmentů (pixelů).
Fragment Shader
						
							- Fragment shader je aplikovaný na každý fragment (pixel) rasterizovaných elementů.
- Výstup fragment shaderu se uloží do framebufferu a zobrazí
Miniální Fragment Shader
<!DOCTYPE html>
<html><body>
<canvas id="c03"></canvas>
<script type="text/javascript">
	var canvas = document.getElementById("c03");
	var gl = canvas.getContext("webgl");
	var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
	gl.shaderSource(fragmentShader,
		'void main(void) {gl_FragColor = vec4(1, 1, 1, 1);');
	gl.compileShader(fragmentShader);
	var program = gl.createProgram();
	gl.attachShader(program, fragmentShader);
	gl.linkProgram(program); gl.useProgram(program);
	gl.clearColor(0.8, 0.3, 0.3, 1.0);
	gl.clear(gl.COLOR_BUFFER_BIT);
</script>
</body></html>
					
					
					Příklad minimálního Fragment Shaderu
					Demonstrační program má opět drobnou nevýhodu: fragment shader nic nedělá, protože nemá žádné vstupní fragmenty.
					
					
				
				
					Shadery a datové typy
					
						- Jednoduché datové typy: void, bool, int, float
- Vektory floatů: vec2, vec3, vec4
- Vektory booleanů: bvec2, bvec3, bvec4
- Vektory integerů: ivec2, ivec3, ivec4
- Čtvercové matice floatů: mat2, mat3, mat4
- Textury: sampler2D, samplerCube
- Jednorozměrné pole a struktury
Konstrukce pro řízení shaderů
					for(;;) {}
while() {}
do {} while()
						Podmínky:
if() {}
if() {} else {}
						Skoky:
break, continue, return, discard
						V shader si můžete definovat vlastní funkce:
float add(float a, float) {return a + b};
					
				
				
					Vestavěné funkce shaderů
					Je jich cca 60. Příklady nejpoužívanějších: sin(), asin(), cos(), acos(), tan(), atan(), pow(), exp(), log(), exp2(), log2(), sqrt(), abs(), floor(), ceil(), mod(), min(), max(), atd.
					Kompletní seznam je například v Quick Reference Card 
				
				
					Double-buffering
					
						“WebGL: double-buffering batteries included!”
					
					
						- Framebuffer není ve skutečnosti jeden, ale jsou dva: přední a zadní.
- Do zadního se postupně vykresluje
- Přední je zobrazován uživateli
- Při dokončení vykreslování se buffery prohodí
- Zamezuje problikávání a vzniku rušivých artefaktů
Z-Buffer alias paměť hloubky
					
				
				
					Vstupní data: vertexy & indexy
					
						- Nejprve je nutné říci, že vertex shader bude používat nějaká vstupní data a jak je bude používat:
attribute vec3 pos;
void main(void) { gl_Position = vec4(pos, 1); }
						Vstupní data je nutné předat do vertex shaderu pomocí ArrayBufferu
					
				
				
					
						ArrayBuffer & typové pole
						
							- Data jsou mezi aplikací psanou v Javascriptu a shadery předávána v tzv. ArrayBufferech
- ArrayBuffer se vytváří pomocí tzv. typového pole (novinka v HTML5).
- Typové pole může obsahovat data pouze jednoho typu.
								- Uint8Array, Uint16Array, Uint32Array
- Int8Array, Int16Array, Int32Array
- Float32Array, Float64Array
Předáváme data pomocí ArrayBuffer
						
							- Nejprve řekneme, do jakého atributu budeme data předávat
var posLoc = gl.getAttribLocation(program, "pos");
gl.enableVertexAttribArray(posLoc);
							Následně vytvoříme ArrayBuffer, naplníme ho obsahem z typového pole a propojíme ho s atributem pos
var posBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer); // aktivní buffer
var vertices = [0.0, 0.0, 0.0];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices),
    gl.STATIC_DRAW);
gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0)
						
					
					
						Předávaná data
						
							- Data předávaná do vertex shaderu nemusí a nejsou být pouze souřadnice vertexů.
- Může jít o barvu vertexů, UV souřadnice, matice, normálové vektory, atd.
Vykreslení elementů
						
							- Elementy (v tomto případě body) následně vykreslíme pomocí (vykreslujeme data z aktivního bufferu):
gl.drawArrays(gl.POINTS, 0, vertices.length/3);
							Podporované typy elementů: POINTS, LINE_STRIP, LINE_LOOP, LINES, TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES
						
					
				
				
					
						Elementy a ArrayBuffer
						
							- Složitější útvary než vertexy (hrany a trojúhelníky) je vhodné vykreslovat pomocí indexů do bufferu vertexů.
- K tomu slouží ElementArrayBuffer:
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
var indices = [0, 1, 2];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
    new Uint8Array(indices), gl.STATIC_DRAW);
							
						
					
					
						Vykreslení elementů
						
							- Elementy pomocí indexů vykreslujeme následovně (opět se data berou z aktuálního bufferu)
gl.drawElements(gl.LINES, 6, gl.UNSIGNED_BYTE, 0);
							Podporované typy elementů jsou stejné: POINTS, LINE_STRIP, LINE_LOOP, LINES, TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES
						
					
				
				
					Souřadné systémy
					
						- Je dobré si povšimnout, že hodnoty, které vystupují z vertex shaderu jsou v homogenních souřadnicích a následně jsou převedeny ho kartézské soustavy souřadné.
- Pohledové souřadnice mají počátek soustavy souřadné v prostředku a v pravém horním rohu je bod [1, 1, 0].
- V neposlední řadě je třeba zmínit soustavu souřadnou canvasu. Počátek soustavné je v levém horním rohu. Bod [width, height] je v pravém dolním rohu.
Varying proměnné
					
						- Pokud je nějaká promenná označena ve vertex shaderu klíčovým slovem varying, tak během rasterizaci elementů dochází k její lineární interpolaci. Pro každý fragment elementu (úsečka, trojúhelník) je spočítána hodnota.
varying vec3 color;
					
				
				
					Uniform proměnné
					
						- Proměnné označené klíovým slovem unform jsou neměné pro celý vertex nebo fragment shader.
- Nejčastěji se používají pro matice