Tulipa niin visainen pähkinä, että pakko kysyä: Piirrän kuvan 2d-polygonina. Tekstuurin sidon SDL_Surface*:sta, johon on asetettu colorkey:llä läpinäkyvä väri. Nythän on niin, että haluaisin sen piirtävän POLYGONISTA vain sen alueen, jonka päällä olevassa tekstuurissa oleva alue EI ole asetettu läpinäkyväksi. Mites tämän teen? Googlella ei tuntunut löytyvän (tai en keksinyt oikeita hakusanoja).
Colorkey ei auta. Muuta tekstuurisi ensin 32-bittiseen muotoon niin, että siinä on erillinen alfakanava. Voit tehdä muunnoksen vaikkapa silmukassa getpixelillä ja setpixelillä. SDL:n dokumentaation perusteella muunnoksen pitäisi onnistua myös niin, että luot uuden 32-bittisen pinnan, joka on kokonaan läpinäkyvä, ja piirrät tuon vanhan pinnan sen päälle, jolloin piirretyistä pikseleistä tulee läpinäkymättömiä.
Öh... Entä sitten? Ei kai se OpenGl ilman lisäasetuksia sitä ymmärrä?
Tietenkin lataat sen pinnan sitten nelikomponenttisena RGBA-formaatilla. (Lue glTexImage2D:n dokumentaatiosta.) Ei siihen sen kummempaa tarvita, paitsi tietysti sitten vielä glEnable(GL_BLEND); ja toiveisiisi sopiva glBlendFunc-kutsu.
Nyt sain toimimaan niin, että se ottaa maskista läpinäkyvyyden siihen kuvaan put- ja getpixeleillä. Nyt on kuitenkin niin, että halusin nimenomaan myös takana olevan kuvan näkyvän läpi. Onkos tähän olemassa ratkaisua? Nyt se nimittäin vain piirtää polygonin varsinaisen värin siitä takaata...
Nyt olet tainnut tehdä jotain väärin. Kyllä sen taaemman sieltä pitäisi näkyä, jos luot ihka oikean alfakanavan. Jos piirrät päällemmän ensin, taaempi näkyy vain, jos etummaisessa on kokonaan läpinäkyviä pikseleitä (alfa 0).
Tässä koodi:
Uint8 rp,gp,bp,ap,tp; Uint32 pixel; SDL_LockSurface(Tileset::img); for(int b=0; b<Tileset::img->h; ++b){ for(int a=0; a<Tileset::img->w; ++a){ pixel=getpixel(Tileset::mask,a,b); SDL_GetRGBA(pixel, Tileset::mask->format, &ap,&rp,&bp,&gp); pixel=getpixel(Tileset::img,a,b); SDL_GetRGBA(pixel, Tileset::img->format, &rp, &gp, &bp, &tp); putpixel(Tileset::img, a, b, SDL_MapRGBA(Tileset::img->format,rp,gp,bp,ap)); } } SDL_UnlockSurface(Tileset::img);
Edit: kuvat loin näin: SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, rmask, gmask, bmask, amask);
Jos kerran luot kuvat noin, niin mistä niiden data sitten on peräisin? Mikset voi jo latausvaiheessa tehdä järkevästi?
Koodia kopioidessa olisi hyvä myös vähän valaista, mitä nämä eri pinnat sisältävät tai mitä koodin on tarkoitus tehdä.
Ilmeisesti tarkoituksena on, että mask
sisältää punaisessa värissään sen, mitä kuvaan on tarkoitus asettaa alfakanavaksi? Jos näin on, koodi taitaa tuolta osin olla kunnossa.
Kun nyt ilmeisesti koodaat aika paljon ja teet aika paljon asioita, joita et aivan kokonaan itse ymmärrä, niin kannattaa samalla opetella vähän sellaista asioiden selvittämisen taitoa. Esimerkiksi tuossa tapauksessa järkevä lähestymistapa olisi kokeilla meneltemää muutaman pikselin kokoisella pinnalla, jolloin voisit tulostaa (lukuina) koko pinnan sisällön, koko maskin ja koko lopputuloksen ja päätellä näiden perusteella, tekikö koodi sen, mitä oli tarkoitus.
Jos käytät depth-testiä eri "tasojen" tekoon niin piirräthän taustan ennen polygonia. Tällöin voit toki käyttää alphatestiä estämään läpinäkyvien pikseleiden piirtymisen depth-puskuriin.
Kuvan lataan bmp:stä, muutan vain sen blittaamalla sen tohon kuvaan opengl:n tekstuuriksi sopivaksi. Maskissa se kuva on ihan harmaan eri sävyinä, otetulla värillä ei ole merkitystä. Läpinäkyvyyden kyllä saan aikaan niin, että se jättää tekstuurin piirtämättä, mutta alla näkyy paljas polygoni.
Miksi sieltä mikään paljas polygoni näkyisi? Jos teksturointi on käytössä, ei ole mitään paljasta polygonia, vaan polygonin värin korvaa tekstuurista selvitetty väri. Muutatko nyt varmasti kuvasi läpinäkyväksi etkä esimerkiksi valkoiseksi, kuten tuon perusteella kuulostaisi? Lataatko tekstuurin oikein? Yms, yms.
Teepä nyt nuo aiemmin esittämäni testit ja kerro itse, mikä on vikana, niin mietitään sitten, millä se korjataan.
Tämän käskyn voit tarvita kutsua jotta läpinäkyvyys toimii toivotulla tavalla:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Nyt sain toimimaan tuon glBlendFunc:in kanssa! Piti vain asettaa glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);. Nyt toimii hyvin, kiitos avusta.
Aihe on jo aika vanha, joten et voi enää vastata siihen.