Tervehdys kaikki,
Olen ajattellut tehdä peliini bumpmappaus järjestemän, jonka avulla voisin saada peliini hieman realistisemman näköiseksi. Noh olen tässä nytten tämän viikon pohdiskellut valonkäyttäytymistä reali maailmassa ja nytten on päähän kehittynyt jonkinlainen kuva valonkäyttäytymisestä.
Noh nytten pitäisi sitten alkaa toteuttamaan tuota bumpmappausta. Ideani on siis seuraavanlainen.
Luodaan objekteille syvyyskartta, johon piirretään objektien syvyydet, eli mitä tummempi pikseli sitä "syvempi" tai kauempana kamerasta se on.
Tämän jälkeen käydään kuva pikseli pikseliltä läpi, jossa siin haetaan syvyyskartasta pikselin syvyys sekä katsotaan miten kaukana pikseli on valon lähteestä.
Seuraavaksi haen pikselin viereisten pikselin syvyydet, jonka jälkeen lasken pikselille arvon. Eli viereisten pikselin avulla pystyn tarkistamaan, että onko esim viereinen pikseli korkeampi ja pääseekö valo valaisemaan pikseliä jota ollaan värjäämässä.
Eli suomeksi sanottuna ideani on laskea pikselien valon tuottama väriarvot lukemalla arvoja syvyyskartasta ja viereisitä pikseleistä.
...kysymys tuleekin, että onko tässä minun ideassani mitään järkeä, vai onko matemaattinen laskenta tapa parempi, kuten esim. putkassa olevan koodivinkkissä on tehty.
Toivottavasti saitte selkoa.
-. Kiitos
Ensinnäkin valonlähteen etäisyys vaikuttaa myös, se on pakko huomioida. Lisäksi tuolla tavalla valaiset pikselit aivan väärin: entä jos pikseli on syvän kuopan pohjalla mutta juuri viereiset pikselit ovatkin samassa tasossa? Pitäisi siis käydä läpi koko jana valonlähteeseen asti.
Metabolix kirjoitti:
Ensinnäkin valonlähteen etäisyys vaikuttaa myös, se on pakko huomioida. Lisäksi tuolla tavalla valaiset pikselit aivan väärin: entä jos pikseli on syvän kuopan pohjalla mutta juuri viereiset pikselit ovatkin samassa tasossa? Pitäisi siis käydä läpi koko jana valonlähteeseen asti.
Juu ton valonetäisyyden laskemisen kyllä tiesin, mutta unothu kirjottaa tuohon. :) ...hmm, eli siis onko paras tapa tuo tapa mitä putkan koodivinkeissä oleva koodi käyttää, vai olisiko tuo toimiva idea, jos tosiaa kävisi valon läpi jana janalta objektiin.
Edit: Itse asiassa kirjoitihan tuohon kysymyseeni sen, että lasken valonetäisyyden pikselistä?
Tässä pieni kuva havainto. Tässä punaiseen pallo objektiin kodistetaan valoa, ja tältä se näyttäisi ilma syvyys karttaa. Sininen linja kuvaa valon sädettä jana joka käydään läpi valon alkamis pisteestä valon vaikutus alueen loppuun.
Seuraavassa suuret numerot ovat korkeampia kohtia:
3333 3999 3911 3912
Tutkitaan oikean alakulman (korkeus 2) valaistusta, kun valo on vasemmassa yläkulmassa (korkeus 3). Omien sanojesi mukaan tutkit pikseliä ja sitä ympäröiviä pikseleitä. Niiden mukaan 2 on korkein kohta ja 1:t ovat alempana, joten korkeudelta 3 tuleva valo valaisee kohdan. Kuitenkin välissä on seinä (korkeus 9), jota ei voi huomata, jos ei käy läpi kaikkia pikseleitä valon ja valaistavan kohdan välistä.
Olet ehkä ajatellutkin tätä jo, mutta viesteistäsi tämä minusta puuttuu. :) Valon etäisyyden laskeminen oikeilla kaavoilla on sitten asia erikseen ja liittyy lähinnä siihen, miten valo himmenee kauemmas mennessä ja millaiset reunat spottivaloille tulee.
Aivan juuri tuon kaiken olen noin miettinytkin mitä kirjoitit, tosin ainut mitä en vielä ole keksinyt, on juurikin nuo valotus kaavat. Eli millä kaavoilla nuo pikselien valotus tapahtuu..
...mutta jatkan kokeilua. :)
Edit1: Piirsin tuon sinun syvyyskarttasi mukaan kuvan. Eli siis teen niin, että rgb( 100, 100, 100) kuvaa nollaa ja esim. 1 = 10 = 110 tai 9 = 90 = 190. Kuva on hyvin pieni enkä jaksanut alkaa isontaa. :) Vasemman puoleinen kuva on ilman valo janaa ja oikean puoleinen kuvaa punaista valojanaa joka käydään läpi?
Yksinkertainen menetelmä (oikeellisuudesta en tiedä) olisi etsiä tuolta janalta se kohta, joka rajoittaa näkyvyyttä eniten. Jos tilannetta katsotaan sivulta, asia on aivan selvä:
O ## # b ### # a # ##########
Valo (O) ei valaise kohdetta a, koska välissä oleva seinä on liian korkea. Kohde b valaistuu, koska valo pääsee seinän yli. Täytyy siis tutkia korkeuden muutosta valosta kohteeseen ja tarkistaa, ettei mikään välissä ole viivan yläpuolella.
Tällaiset laskut ovat lopulta yksinkertaisia, kunhan ne saa paperilla kohdalleen, mutta kun puhutaan optimoinnista, homma menee mutkikkaaksi: jos joka pikselille käydään läpi kaikki lähialueen valoihin johtavat janat, käydään läpi esimerkiksi 640 * 480 * 4 janaa * 200 pikseliä / jana = 246 miljoonaa pikseliä. Mahdotonta.
Tuli mieleeni, että 2D-tilanteessa voisi soveltaa yksinkertaistettua versiota tästä.
Jos maisema on staattinen, tällaiset kikkailut eivät maksa vaivaa; helpompi on vain piirtää ne varjot tasoon ja liikkuvien asioiden varjot jollain yksinkertaisella blob-varjomenetelmällä.
Mitä siis tarkalleen yrität tehdä? Sinulla on 2D-peli, josta haluat hienomman näköisen? Ratkaisu: piirrä hienommat (staattiset) grafiikat. Jos suurin ongelma on mielestäsi valaistus, saat sen kuntoon tekemällä grafiikat käyttäen apuna 3D-mallinnus/piirto-ohjelmia, kuten esim. Blenderiä, joilla saat valaistuksen niin "oikeanlaiseksi" kuin pystyt määrittelemään.
Dynaamisen valaistuksenkin (esim. objektit voivat liikkua suhteessa valonlähteisiin) saa luultavasti aika mukavan näköiseksi staattisen 2D-grafiikan fiksulla käytöllä ja yksinkertaisilla menetelmillä, kuten koko objektin tummennus paikan mukaan. 2D-pikselikorkeuskarttojen käyttö valaistuksen laskemiseen reaaliajassa ei taida olla missään mielessä kovin hyvä vaihtoehto. Jos varjojen ja valojen pitää näyttää paremmilta kuin staattisella 2D:llä saa aikaiseksi, niin suosittelisin siirtymään suosiolla 3D-pohjaiseen systeemiin.
Itse olen tässä pähkäillyt seuraavanlaisen laskukaavan.
3333 3999 3911 3912 valon_vahennys_prosentti = valon_etaisyys / sade * 100 valon_vahennys = ( valon_max_kirkkaus * valon_vahennys_prosentti / 100 ) pikselin_valo_prosentti = pikselin_korkeus / 255 * 100 pikselin_kirkkaus = ( valon_max_kirkkaus * pikselin_valo_prosentti / 100 ) pikselin_vahennys = ( pikselin_kirkkaus * valon_vahennys_prosentti / 100 ) ve = ( ( pikselin_kirkkaus - pikselin_vahennys ) + ( valon_max_kirkkaus - valon_vahennys ) ) / 2 v = varjo 130 -> ve 190 -> ve 100 -> ve - ((190_ve / 2 / 4) * 4) 120 -> ve - ((190_ve / 2 / 4) * 3) v -> ((190_ve / 2 / 4) * 2) v -> ((190_ve / 2 / 4) * 1) v -> ((190_ve / 2 / 4) * 0)
No onko sillä saavutettu lopputulos tyydyttävä? Jos (kun) ei, mutta haluat silti koodata valaistusjuttuja itse, niin kannattaa varmaan ottaa hieman mallia oikeasti käytetyistä ja hyviksi todetuista tavoista mallintaa valaistusta.
Joitakin kenties relevantteja sivuja Wikipediassa:
http://en.wikipedia.org/wiki/Shading
http://en.wikipedia.org/wiki/
http://en.wikipedia.org/wiki/Rendering_
Jos haluat välttämättä laskea valaistusta pikselikorkeuskarttojen avulla, niin kannattanee aloittaa laskemalla (keksimällä) korkeuskartan kuvaaman pinnan kullekin pikselille normaali.
Ahaa,
Pitääpä tutkia tarkemmin noita jos vaikka sais jotain aikaseksi noiden avulla...
...vai onko niin, että olen haukkaamassa liian suurta kakunpalaa, eli kannattaako 2d ylipäätäntä tuota valojärjestelmää tehdä, vai onko se vain suuruuden havittelua, joka ei tule toimimaan käytännössä.
En sanoisi, ettei 2D-peliin voisi tai kannattaisi tehdä jonkinlaista valaistussysteemiä, mutta pikselikorkeuskarttojen käyttö on mielestäni varsin huono lähestymistapa.
Kannattanee tosiaan lähteä liikkeelle valmiiksi valaistuista/varjostetuista bittikarttakuvista, joiden valaistusta ohjelmassa mahdollisesti muutellaan piirtovaiheessa yksinkertaisilla menetelmillä.
Eräs mahdollinen tapa (ei välttämättä paras) muuttaa valaistusta löytyy Allegro-kirjaston esimerkkiohjelmasta "exshade". Toteutuksen löydät lähdekoodista (src/gsprite.c
)
Aihe on jo aika vanha, joten et voi enää vastata siihen.