Kube med teksturerte sider
Se kodeeksemplet som viser en teksturert kube. Legg merke til bruk av to shaderpar, et for koordinatsystemet og et for kuben.
Legg også merke til bruk av "backface culling". Dette for at ikke innersiden av kubens flater skal vises når den roterer. Slår man av culling vil kuben se slik ut:
Bruke deler av teksturen
En tekstur kan fordeles utover modellen vha. uv-koordinatene. Anta at følgende tekstur skal brukes til å kle sidene av en kube. Her er teksturkoordinatene som må brukes angitt for å kunne teksturere kubens ulike sider.
Terningtekstur (fra Koilz)
Ved hjelp av denne teksturen skal kuben tekstureres som vist i følgende figur:
Kubesiden som skal vise 1-tallet vil bestå av to trekanter. Verteksposisjonene til denne siden (forsiden) er definert i forhold til følgende figur:
Under ser vi utsnitt fra kodeeksemplet som det refereres til:
//Definerer to trekanter per side:
let pos = new Float32Array([
//Forsiden (1-tallet):
-1, 1, 1, //v1
-1,-1, 1, //v2
1,-1, 1, //v3
-1,1,1, //v4
1, -1, 1, //v5
1,1,1, //v6
//Høyre side:
1,1,1,
. . .
. . .
]);
Her er de 6 verteksposisjonene til kubens forside definert (tilsvarende for resten av kubens sider).
Verteksene definerer to trekanter som skal kles med den delen av teksturen som inneholder 1-tallet. Siden 1-tallet er en del av teksturen må vi bruke fire ulike uv-koordinater og knytte disse til de 6 verteksene:
Disse assosieres med de ulike verteksene som vist i figuren under:
Dette gir følgende kopling mellom verteksposisjon og uv-koordinater:
Verteks
|
Posisjon |
Uv-koordinat |
v1 |
-1,1,1 |
0,1 |
v2 |
-1,-1,1 |
0,0.5 |
v3 |
1,-1,1 |
0.33,0.5 |
v4 |
-1,1,1 |
0,1 |
v5 |
1,-1,1 |
0.33,0.5 |
v6 |
1,1,1 |
0.33,1 |
Du finner komplett eksempel blant kodeeksemplene.
Oppgave
Finn/lag din egen terningtekstur med tall, terningprikker e.l. La teksturen bestå av to kolonner og tre rader, f.eks. slik:
Sørg for å kle terningen med dette.
Teksture wrapping / tiling
Hittil har sagt at teksturkoordinatene til et bilde er lik 0,0 i nedre venstre hjørne og 1,1 i øvre høyre hjørne. Dette gjelder selv om bildet ikke er kvadratisk. Det er også mulig å angi teksturkoordinater utenfor dette området, f.eks. slik:
Bruker dette sammen med gl.REPEAT:
Figuren under viser vertekser med tilhørende UV-parametre:
Eksempel:
Bruker vi nå følgende tekstur:
vil det gi følgende resultat:
Samme tekstur legges nå på rektanglet i et 5x5 rutenett. NB! Her må vi bruke en bildefil med bredde og høyde lik 2n piksler. Teksturparametrene som vist over er standard og man får samme resultat uten å ha satt dem som vist.
Denne teknikken kan være veldig besparende dersom man har store flater som skal kles med «ensformig» tekstur, som f.eks. en gresslette, en murvegg o.l. Man kan laste en liten .png som kan «kle» store flater. Her er et eksempel med en murvegg der vi bruker følgende tekstur:
Resultat:
Ser vi nøye på denne flaten ser vi fortsatt at flaten er dekt av 5x5 teksturer. For å unngå dette er det viktig at teksturen er laget slik at den «sømløst» kan plasseres side ved side.
Brukes denne teksturen:
får vi følgende resultat:
Det er også mulig å speile annenhver «teksturcelle» ved å bruke følgende parametre:
får vi følgende resultat på teksturen som ble vist tidligere:
Her speiles teksturen annenhver gang.
Blande teksturer
I foregående eksempler ble fargen til hvert fragment bestemt av teksturen vha. shaderfunksjonen texture2D(uSampler, vec2(vTextureCoordinate.s, vTextureCoordinate.t)). Shadervariabelen uSampler settes fra Javascript-koden og er assosiert med teksturen som skal brukes til å gi fragmentet farge.
Variabelen vTextureCoordinate er interpolert på veien fra verteks- til fragmentshaderen og tilsvarer uv / st -posisjonen for aktuelt fragment (dvs. fragmentet som fragmentshaderen kjører for).
Funksjonens texture2D() henter med andre ord farge fra aktuell tekstur (uSampler) vha. vTextureCoordinate.s og vTextureCoordinate.t og tilordner farge til gl_FragColor som returneres fra fragmentshaderen.
Vi har også sett hvordan vi kan blande teksturfarge med verteksfarge. WebGL har også muligheten til å blande farge fra flere teksturer (se også Greggman, 2013). For å få til dette må man laste antall bildefiler som skal brukes og tilsvarende antall texture-objekter opprettes. I tillegg må man bruke flere «sampler» variabler. Hver av disse assosieres med et texture-objekt. Fragmentshaderen må endres slik at den mottar flere sampler-verdier og returnerer produktet av fargene fra teksturene, slik:
Legg merke til følgende:
- Følgende gjør at man kan bruke bilder av vilkårlig størrelse:
- To bilder laster før kall på initSquareBuffer(textureImage1, textureImage2).
- Det er to globale texture-variabler (squareTexture1 og squareTexture2) og dermed to textureobjekter.
- Shaderne er endret som vist over.
- To samplervariabler sendes til fragmentshaderen.
Som vist over er det nå definert to «samplere» i fragmentshaderen, uSampler0 og uSampler1. Disse brukes videre for å hente farge fra de to teksturene, slik:
Koplingen til uSampler0 og uSampler1 gjøres som en del av oppstartskoden, f.eks. i initTextureShaders(), som vist tidligere:
Verdiene til uSampler0 og uSampler1 settes i draw() metoden som vist tidligere:
Her gir vi verdien 0 til uSampler0 og 1 til uSampler1. Videre aktiveres gl.TEXTURE0 og teksturen som ligger i squareTexture1 bindes med gl.TEXTURE0. Tilsvarende for gl.TEXTURE1 og squareTexture2.
I fragmentshaderen kalles først funksjonen texture2D(…) med uSampler0 som første paremeter. Denne har nå verdien 0 og indikerer at texture2D() skal bruke teksturen som er assosiert med gl.TEXTURE0. Tilsvarende for kall på texture2D(uSampler1, …) som nå henter farge fra teksturen knyttet til gl.TEXTURE1.
Fargene som hentes fra de to teksturene multipliseres og resultatet tilordnes gl_FragColor.
Mipmapping
Teknikken går ut på å bruke teksturer/bildefiler med ulik størrelse. Bildet som man tar utgangspunkt er mipmap level 0 (et av argumentene til texImage2D() metoden). Fra dette genereres det flere mindre bilder, enten automatisk av WebGL eller manuelt ved hjelp av et grafisk verktøy.
Utgangsbildet (level 0) må ha størrelse tilsvarende 2n x 2n piksler der n = 0,1,2,3 osv.
Savner litt mer informasjon om MIP mapping.
SvarSlettHvorfor brukes dette?
Hva er Moiré-Patterns?
Hvorfor oppstår Moiré-Patterns?
Hvordan velger texture2D hvilken level som skal brukes?