Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
1
Szécsi László 3D Grafikus Rendszerek 4. labor
2
Geometria JSON-ból IndexedTrianglesGeometry.js a QuadGeometry.js mintájára a konstruktor kapjon egy mesh-leíró objektumot (ahogy az a JSON fileból jön) azért nem a filenevet adjuk át, mert egy fileban több mesh lehet vertices tulajdonság: 3n db koordináta folyotonos tömbben normals tulajdonság: 3n db érték folyotonos tömbben texturecoords tulajdonság: 2n db értéket tartalmazó folyotonos tömbök tömbje (de tipikusan csak egy textúrakoordináta-készlet van) faces tulajdonság: 3 indexet tartalmazó tömböcskék tömbje egy folytonos tömböt lehet belőle gyártani így: [].concat.apply([], jsonObject.faces)
3
Index buffer az indexek száma nem fix
a konstruktorban el kell tárolni tulajdonságként rajzoláskor fel lehet használni
4
MultiMesh.js - betöltés
var MultiMesh = function( gl, jsonModelFileUrl, materials) { this.meshes = []; var request = new XMLHttpRequest(); request.open("GET", jsonModelFileUrl); var theMultiMesh = this; request.onreadystatechange = function () { // next slide }; request.send();
5
MultiMesh.js – betöltés után
if (request.readyState == 4) { var meshesJson = JSON.parse(request.responseText).meshes; for (var i = 0; i < meshesJson.length; i++) { theMultiMesh.meshes.push( new Mesh( new IndexedTrianglesGeometry(gl, meshesJson[i]), materials[i] )); }
6
MultiMesh.js – rajzolás
MultiMesh.prototype.draw = function(gl){ for (var i = 0; i < this.meshes.length; i++) { this.meshes[i].draw(gl); } };
7
Skálázni, forgatni kell
8
3D kamera PerspectiveCamera object must set view, projection matrices
moveable by mouse and WASD keys
9
Kamera paraméterek var PerspectiveCamera = function() { this.position = new Vec3(0.0, 0.0, 0.0); this.ahead = new Vec3(0.0, 0.0, -1.0); this.right = new Vec3(1.0, 0.0, 0.0); this.up = new Vec3(0.0, 1.0, 0.0); this.yaw = 0.0; this.pitch = 0.0; this.fov = 1.0; this.aspect = 1.0; this.nearPlane = 0.1; this.farPlane = ;
10
Tagváltozók mozgatáshoz
this.speed = 0.5; this.isDragging = false; this.mouseDelta = new Vec2(0.0, 0.0);
11
Mátrixok this.viewMatrix = new Mat4(); this.projMatrix = new Mat4(); this.rayDirMatrix = new Mat4(); this.viewProjMatrix = new Mat4(); this.updateViewMatrix(); this.updateProjMatrix(); this.updateRayDirMatrix(); };
12
Világ felfelé iránya PerspectiveCamera.worldUp = new Vec3(0, 1, 0);
13
View mátrix számítása PerspectiveCamera.prototype.updateViewMatrix = function(){ this.viewMatrix.set( this.right.x , this.right.y , this.right.z , 0, this.up.x , this.up.y , this.up.z , 0, -this.ahead.x , -this.ahead.y , -this.ahead.z , 0, 0 , 0 , 0 , 1).translate(this.position).invert(); this.viewProjMatrix.set(this.viewMatrix).mul(this.projMatrix); };
14
Proj mátrix számítása PerspectiveCamera.prototype.updateProjMatrix = function() { var yScale = 1.0 / Math.tan(this.fov * 0.5); var xScale = yScale / this.aspect; var f = this.farPlane; var n = this.nearPlane; this.projMatrix.set( xScale , 0 , 0 , 0, 0 , yScale , 0 , 0, 0 , 0 , (n+f)/(n-f) , -1, 0 , 0 ,2*n*f/(n-f), 0); this.viewProjMatrix.set(this.viewMatrix). mul(this.projMatrix); };
15
RayDir mátrix számítása
PerspectiveCamera.prototype.updateRayDirMatrix = function(){ // önállóan megoldandó feladat // de ráér // az env mapping háttérhez kell csak };
16
Mozgatás: yaw, pitch drag
PerspectiveCamera.prototype.move = function(dt, keysPressed) { if(this.isDragging){ this.yaw -= this.mouseDelta.x * 0.002; this.pitch -= this.mouseDelta.y * 0.002; if(this.pitch > 3.14/2.0) { this.pitch = 3.14/2.0; } if(this.pitch < -3.14/2.0) { this.pitch = -3.14/2.0; this.mouseDelta = new Vec2(0.0, 0.0);
17
Mozgatás: főirányok a szögekből
this.ahead = new Vec3( -Math.sin(this.yaw)*Math.cos(this.pitch), Math.sin(this.pitch), -Math.cos(this.yaw)*Math.cos(this.pitch) ); this.right.setVectorProduct( this.ahead, PerspectiveCamera.worldUp ); this.right.normalize(); this.up.setVectorProduct(this.right, this.ahead); }
18
Mozgatás gombokkal if(keysPressed.W) { this.position.addScaled(this.speed * dt, this.ahead); } if(keysPressed.S) { this.position.addScaled(-this.speed * dt, this.ahead); if(keysPressed.D) { this.position.addScaled(this.speed * dt, this.right); if(keysPressed.A) { this.position.addScaled(-this.speed * dt, this.right); if(keysPressed.E) { this.position.addScaled(this.speed * dt, PerspectiveCamera.worldUp); if(keysPressed.Q) { this.position.addScaled(-this.speed * dt, PerspectiveCamera.worldUp);
19
Mátrixok frissítése this.updateViewMatrix(); this.updateRayDirMatrix(); };
20
Eseménykezelők – meg is kell hívni őket!
PerspectiveCamera.prototype.mouseDown = function() { this.isDragging = true; this.mouseDelta.set(); }; PerspectiveCamera.prototype.mouseMove = function(event) { this.mouseDelta.x += event.movementX; this.mouseDelta.y += event.movementY; event.preventDefault(); PerspectiveCamera.prototype.mouseUp = function() { this.isDragging = false;
21
Képméretarány állítása – ezt is meg kell hívni!
// ar: canvas.clientWidth / canvas.clientHeight PerspectiveCamera.prototype.setAspectRatio = function(ar) { this.aspect = ar; this.updateProjMatrix(); };
22
Rakjuk össze! ortho kamera lecserélése mélységteszt bekapcsolása
eseményfigyelők bekötése GameObject2D jó lehet még de figyeljünk rá, hogy a modelViewProjMatrix beállítása rajzoláshoz összhangban legyen a PerspectiveCamera tulajdonságaival GameObject3D csak a forgatásban térne el
23
3D transzformáló vertex shader
kell neki a modelViewProjMatrix továbbra is de kell egy modelMatrix uniform is nincs benne a kameratrafó modellből világkoordintákba transzformál új varying kimenet: worldPos és még kell egy modelMatrixInverse uniform a normálvektorok transzformálásához ezt most bal oldalról szorozzuk, mert az inverz transzponálttal kell a normálvektort transzformálni új varying kimenet: worldNormal
24
Fragment shader a 3D trafó ellenőrzéséhez
rajzoljuk ki a worldNormal-t színként
25
Várt eredmény abs(normal)-lal
26
Egyszerű árnyaló FS legyen egy fényirány-vektor
normálvektor és fényirány közötti szög koszinusza az irradiancia texúrából olvasott színt moduláljuk ezzel
27
Várt eredmény
28
Environment mapping doboztextúra betöltése
új FS ami kiszámolja az ideális visszaverődési irányt és kiolvassa a textúrát
29
TextureCube.js - betöltés
var TextureCube = function(gl, mediaFileUrls) { pendingResources[mediaFileUrls[0]] = ++pendingResources[mediaFileUrls[0]] || 1; this.mediaFileUrls = mediaFileUrls; this.glTexture = gl.createTexture(); this.loadedCount = 0; this.images = []; var theTexture = this; for(var i=0; i<6; i++){ this.images[i] = new Image(); this.images[i].onload = function() { theTexture.loaded(gl); } this.images[i].src = mediaFileUrls[i]; } };
30
TextureCube.js – erőforrás létrehozása
TextureCube.prototype.loaded = function(gl){ this.loadedCount++; if(this.loadedCount < 6) return; gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.glTexture); for(var i=0; i<6; i++){ gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.images[i]); } gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.generateMipmap(gl.TEXTURE_CUBE_MAP); gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); if( --pendingResources[this.mediaFileUrls[0]] === 0 ) { delete pendingResources[this.mediaFileUrls[0]]; };
31
Ez nem kell, ha van reflection
// akkor kéne, ha direktben akarnánk rákötni egy Sampler2D // uniformra. Ha van Material-unk reflectionnel, akkor // a WebGLMath Sampler2D objektuma ezt intézi TextureCube.prototype.commit = function(gl, uniformLocation, textureUnit){ gl.uniform1i(uniformLocation, textureUnit); gl.activeTexture(gl.TEXTURE0 + textureUnit); gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.glTexture); };
32
Tükröző objektum létrehozása
fragment shader gyártsuk le a TextureCube-ot, kössük be a fenti FS-t használó Material-ba, a GameObject használja ezt az anyagot // kell egy sampler uniform uniform samplerCube envmapTexture; // kiolvasni a tükörirányban textureCube( envmapTexture, reflect(-viewDir, normal)) this.skyCubeTexture = new TextureCube(gl, [ "media/posx512.jpg", "media/negx512.jpg", "media/posy512.jpg", "media/negy512.jpg", "media/posz512.jpg", "media/negz512.jpg",] ); this.slowpokeMaterial0. envmapTexture.set ( this.skyCubeTexture);
33
Várt eredmény higany pokemon visszaveri a környezetét
de maga a környezet nem látszik
34
Sugárirány kiszámítása NDC-ből
extra (EVP)-1 -et nevezzük rayDirMatrix-nak
35
Környezet megjelenítése háttérként
extra teljes képernyős téglalapot kell rajzolni (hurrá!) új VS: kiszámolja a sugárirányt át kell adni a képernyőkoordinátából-világkoordináta- mínusz-szempozíció-számító mátrixot (a.k.a. rayDirMatrix) a kamera ezt kiszámolja nem transzformál (mert full viewport quad) z= , minden mőgé FS megkapja a VS-től varying-ben a sugárirányt ezzel címzi a textúrát visszaadja a kapott színt
36
Ne felejtsük el a GameObject adja át a rayDirMatrix-ot
extra Ne felejtsük el a GameObject adja át a rayDirMatrix-ot az új shadereket vegyük be az index.HTML-be gyártsuk le szükséges shader, program, material objektumokat ugyanazt a doboztextúrát kössük be a háttér anyagába, mint amit a tükröző objektuméba legyen quadGeometry legyen egy mesh a quadGeometry és a fenti material használatával legyen egy gameObject a mesh-sel
37
extra Várt eredmény tükröző objektum és háttér
38
Házi feladat válasszon egyet az alábbiak közül:
Phong-Blinn + diffúz árnyalás objektum körül keringő pontfényforrás 3D-ben forgó, ütköző objektumok ütközőgeometria: két gömb per objektum procedurális normal mapping zajfüggvény: random (de fix) irányok mentén koszinuszok összege normálvektor perturbációja zajfüggvény gradiensével env mappinggel kombinálva (háttér is kell)
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.