Back to site
Since 2004, our University project has become the Internet's most widespread web hosting directory. Here we like to talk a lot about web servers, web development, networking and security services. It is, after all, our expertise. To make things better we've launched this science section with the free access to educational resources and important scientific material translated to different languages.

masina za renderovanje


 


Kliknite na sliku da otvorite aplikaciju!

Vau! Šta je ovo?

To je 2D scena koja sadrži 2 svetla i 13 različitih objekata renderovanih u realnom vremenu od strane Javascript biblioteke, koju sam napravio i nazvao Illuminated.js.

Biblioteka je dizajnirana da doda neke fenomenalne efekte na Vaše postojeće aplikacije. Dodavanje dobre atmosfere za vaše aplikacije i igre može napraviti razliku!

Isprobajte editor i Nabavite izvorni kod.

U ovom članku ćemo predstaviti osnovne upotrebe Illuminated.js i APIs, a onda ćemo objasniti kako motor radi korak-po-korak.

Kako mogu da ga koristim?

Biblioteka koristi HTML5 Canvas da iscrta svetla i senke - tako da jednostavno možete da ga otpustite direktno u Vaše postojeće Canvas aplikacije: treba samo da dodate neki kod u rendering funkcije i održavate vezivanje između aplikacije i Illuminated.js objekata.
Ne koristite canvas? Bez brige! U teoriji, ako imate neku postojeću aplikaciju ili igru napravljenu potupuno u DOM-u, možete da koristite Illuminated.js iza ovoga, igrajući se sa z-indeksom.

Početak rada

Osnovni koncepti

Sve klase paketa žive u window.illuminated.

Light opisuje svetlost koju emituje izvor.
OpaqueObject precizira 2D objekat koji se koristi za Lighting.
Lighting definiše osvetljenje svetlošću kroz niz mutnih objekata, svaki objekat zaustavlja svetlo i baca senke.
DarkMask definiše taman sloj koji skriva mračnu oblast koja nije osvetljena nizom svetla. Treba iscrtati na gornjem-sloju da se prikriju predmeti koji su daleko od svetlosti. Ovaj efekat daje bolju atmosferu i savršen je za igru, gde su svetla od suštinskog značaja (gde je skrivanje nevidljivog prostora deo problema).

Primer osnovne scene renderovanja

Kliknite ovde da otvorite ovaj primer.

Svetla i Objekti

Vec2

new Vec2(x, y)

Vec2 predstavlja 2d poziciju ili 2d vektor. Koristi se svuda u Illuminated.js.

Vec2 je inspirisan Box2d Vec2*om, osim što je u Illuminated.js Vec2 vektor nepromenljiv. To znači da svaka metoda kreira novu instancu Vec2 i možete slobodno da koristite istu Vec2 instancu svuda, jer nepromenljivost garantuje da nema izmene svojstava.

Svetla

Za sada smo implementirali samo jednu vrstu svetlosti: Lamp koja je u osnovi radijalni gradijent. Lampa može biti "orijentisana", to znači da osvetljava daleko više u određenom pravcu.

Lamp

new Lamp()
new Lamp({ position: new Vec2(12, 34) })

every parameters:

new Lamp({
  position: new Vec2(12, 34),
  distance: 100,
  diffuse: 0.8,
  color: 'rgba(250,220,150,0.8)',
  radius: 0,
  samples: 1,
  angle: 0,
  roughness: 0
})

Definiše Lamp smeštenu na poziciju, sa maksimalnom emitujućom distancom, diffuse parametri koji definišu prodor svetlosti u objekte.
Radijus definiše veličinu svetlosti. Što je veća veličina, više senke su blaže. Uzorci su važni parametri za glatko definisanje kvaliteta.
Ugao i parametri hrapavosti se koriste za orijentisanje lampe: ugao definiše položaj dok hrapavost definiše hrapavost efekta.

Light metode

Možete lako da kreirate sopstveni tip svetlosti, uvođenjem svoje metode.

.mask(ctx)

Renderuje masku koja predstavlja vidljivost (koristi DarkMask).

.render(ctx)

Renderuje svetlo (bez ikakvih senki).

.bounds()

Vraća povezani pravougaonik svetlosti predstavljajući mesto gde se završava emitovana svetlost. { topleft: vec2, bottomright: vec2 }

.forEachSample(fn)

Primenjuje funkciju fn za svaku poziciju uzorka svetla. Po defaultu, jednom se poziva sa položajem svetlosti.

Netransparentni objekti

U Illuminated.js, objekat koji baca senku se zove netransparentni objekat. Zato svaka vrsta nasleđuje OpaqueObject.

DiscObject i PolygonObject su dva primitivna objekta na raspolaganju.

DiscObject

"DiscObject" je u suštini 2D kružni objekat. Morate definisati njegovu poziciju centra i njegov poluprečnik:

new DiscObject({ position: new Vec2(80,50), radius: 20 })

PolygonObject

PoligonObject, takođe, ima neke izvedene klase koje možete koristiti: RectangleObject, LineObject.

Možete da instancirate ove različite objekte na ovaj način:

new PolygonObject([ new Vec2(0, 0), new Vec2(10, 10), ... ]) // an array of points
new RectangleObject(topleft, bottomright) // topleft and bottomright positions of the rectangle
new LineObject(a, b) // an object defined by the line from a to b.

OpaqueObject metode

Možete lako da kreirate spostvenu vrstu objekta primenom OpaqueObject metoda.

.bounds()

Vraća povezan pravougaonik objekta. { topleft: vec2, bottomright: vec2 }

.contains(point)

Vraća true ako objekat sadrži tačku.

.path(ctx)

Gradi putanju oblika objekta u 2D ​​kontekstu ctx.

.cast(ctx, origin, bounds)

Popunjava sve senke sa ctx projektovanjem nultih tačaka u objektu i u datim granicama.

Lighting i DarkMask

Prethodno definisane klase su predstavljale podatke koje ćemo sada koristiti za osvetljivanje i maskiranje.

Lighting

Lighting definiše osvetljenje jedne svetlosti kroz niz neprozirnih objekata.

new Lighting({ light: light, objects: [ object1, object2, ... ] })

.compute(visina, težina)

će izračunati senke odlivaka.

.cast(ctx)

privući će crne senke na ctx platnu u 2d kontekstu.
Obično ne morate da ga koristite, ako koristite render().

.render(ctx)

privući će svetlo sa svojim senkama na ctx platnu u 2d kontekstu.

DarkMask

DarkMask definiše tamni sloj koji skriva mračnu oblast koja nije osvetljena nizom svetala.

new DarkMask({ lights: [light1, light2, ...], color: 'rgba(0,0,0,0.9)' })

.compute(širina, visina)

izračunaće tamnu masku.

.render(ctx)

privući će tamnu kompjuterizovanu masku na ctx platnu u 2d kontekstu.

o računanju i renderovanju

Lighting i DarkMask objekti imaju compute() i render() metode.

Mislimo da Vi najbolje znate kada da preračunate svetla, jer je to tesno povezano sa aplikacijom koju pravite (nećemo svaki trenutak proveravati, ako se nešto promenilo, Vi to znate).
Pozovite compute() metod kada se nešto promeni u Vašoj sceni, tako da mi onda možemo da preračunamo svetla i senke.

Kako to radi ispod haube?

Illuminated.js deli svoj rad u nekoliko slojeva.

Primer u realnom vremenu

Umetnost komponovanja slojeva

Svi slojevi su sačuvani u Canvas-u koji nam omogućava da ga keširamo. Svetlo se iscrtava pomoću Canvas Radial Gradient samo jednom u keš Canvas-u. To je interesantno jer je gradijent platna procesorski zahtevan
Na kraju, slojevi se kombinuju na globalnom platnu uz pomoć metode drawImage.
Ali biblioteka Vam omogućava da ponovo koristite ove slojeve na način na koji želite.

Metoda platna globalCompositeOperation je veoma korisna za komponovanje slojeva.
Na primer, u sledećem primeru, "Light shadow casting" sloj je kombinovan sa "Light rendering" slojem da bi se generisao "Light rendering with shadows" sloj. Režim komponovanja koji se koristio je “destination-out”, i on uklanja boju odredišne slike gde izvorna slika ima boju.

light.render(ctx);
ctx.globalCompositeOperation = "destination-out";
this.cast(ctx);

Još jedna veoma korisna operacija komponovanja je "lighter" koja dodaje vrednost boje. Ona se koristi za kombinovanje dva osvetljenja.

Kako se senke projektuju

Neki motori renderovanja koriste ray tracing da bi renderovali scenu, koncept veoma blizak fizičkom, koji iz izvora svetlosti kopira dosta zraka sa različitim putevima, koji će se sudarati sa objektom i biće predmet apsorpcije/difrakcije/refleksije u skladu sa osobinama objekta.
Ray casting je vrlo realistično rešenje renderovanja ali i dugotrajno (potrebno Vam je mnogo zraka da izbegnete buku u rezultujućoj slici).
Illuminated.js ne koristi ray tracing jer ima za cilj da bude efikasan za korišćenje u realnom vremenu. Koristi neke heuristike za livenje senki.

Hajde da vidimo kako se senke projektuju za mnogougaoni objekat.

Imamo scenu sa svetlom i trouglom.

Izabrali smo svaku ivicu mnogougla koja je vidljiva od strane svetlosti (i u svetlosnim je granicama).

Za svaku izabranu ivicu smo procenili da generiše površinu mnogougla.

N.B. U trenutnoj implementaciji generisali smo projekciju šestougla da bi se osigurali da ide van svetlosnoh granica, jer kod četvorougla to ne garantujemo, ako je svetlo veoma blizu njega. Korišćeni vektor za projektovanje je dovoljno velik da radi u većini slučejeva, ali je i dalje heuristički.

Koristimo crnu boju u ovoj oblasti mnogougla. Neka poboljšanja se mogu vršti tako da se ne koristi crna boja u obliku / podešavanju prozirnosti.

Za livenje zamućene senke ponavljamo ovaj algoritam za sve "uzorake" svetlosti. Uzorci se distribuiraju oko svetlosti sa "spiralnim algoritmima".

var GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5));
Lamp.prototype.forEachSample = function (f) {
  for (var s=0; s<this.samples; ++s) {
    var a = s * GOLDEN_ANGLE;
    var r = Math.sqrt(s/this.samples)*this.radius;
    var delta = new Vec2( Math.cos(a)*r, Math.sin(a)*r );
    f( this.position.add(delta) );
  }
}

Nastaviće se...

Aktuelna verzija Illuminated.js zahteva više rada, svestan sam nekih grešaka i nekih delova koje treba da popravimo:

  • Implementacija novih vrsta svetala kao što su “Spot”, “Neon”, …
  • Tamna maska ne prati orijentaciju Lampe.
  • Senka livenja objekata kruga nije lepo projektovana, moram da izračunam tangentne linije kruga.
  • Senke ponekad idu pogrešno, posebno kada postoje objekti iza objekata
  • Implementacija uzorkovanja senke je malo bljak i pogrešna (promenom parametara uzorka, menja se providnost senke...)

Uključite se

Isprobajte editor i nabavite izvorni kod.


Published (Last edited): 06-12-2012 , source: http://blog.greweb.fr/2012/05/illuminated-js-2d-lights-and-shadows-rendering-engine-for-html5-applications/