Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C: Paras tapa bumpmappaukseen

Sivun loppuun

kayttaja-3842 [18.09.2009 11:00:15]

#

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

Metabolix [18.09.2009 11:08:10]

#

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.

kayttaja-3842 [18.09.2009 11:25:31]

#

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.

Esimerkkikuva

Metabolix [20.09.2009 17:52:28]

#

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.

kayttaja-3842 [21.09.2009 08:31:47]

#

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?

Kuva

Metabolix [21.09.2009 20:40:01]

#

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ä.

os [21.09.2009 21:21:17]

#

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.

kayttaja-3842 [22.09.2009 11:53:58]

#

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)

os [22.09.2009 16:02:10]

#

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/List_of_common_shading_algorithms
http://en.wikipedia.org/wiki/Rendering_(computer_graphics)

Jos haluat välttämättä laskea valaistusta pikselikorkeuskarttojen avulla, niin kannattanee aloittaa laskemalla (keksimällä) korkeuskartan kuvaaman pinnan kullekin pikselille normaali.

kayttaja-3842 [22.09.2009 16:29:41]

#

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ä.

os [22.09.2009 17:20:11]

#

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)


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta