WebGL Med Three.js Shaders

3D-grafikk i nettleseren har vært et emne av interesse siden introduksjonen. Men hvis du skulle lage appene dine ved hjelp av vanlig gammel WebGL, ville det ta aldre. Nylig har noen virkelig nyttige biblioteker blitt tilgjengelig. Three.js er en av de mest populære, og i denne serien vil jeg vise deg hvordan du får det beste ut av det, for å skape fantastiske 3D-opplevelser for brukerne dine.

Jeg forventer at du skal ha en grunnleggende forståelse av 3D-plass før du begynner å lese denne opplæringen, da jeg ikke vil forklare ting som koordinater, vektorer osv..


Et ord om Shaders

Hvis du allerede vet hva shaders er, kan du hoppe over dette trinnet. Shaders er i utgangspunktet programmer skrevet i GLSL (Graphics Layer Scripting Language), som utføres på GPU. Dette gjør dem svært nyttige, da vi kan ta litt arbeid fra CPUen og sette den på GPUen for å øke ytelsen. Det er to typer: vertex og fragment shaders. Vertex shaders brukes til å endre strukturen til objektet (flytt poengene), og fragment shaders gjør endringer i pikslene som blir trukket.


Trinn 1: Vertex Shader

Vi starter med den enklere. Denne shader vil endre plasseringen av vektorene i masken, noe som resulterer i bevegelsesflater. Sett inn denne koden i av appen din:

 

De type Attributtet til dette skriptet forstås ikke av nettleseren, så det vil ikke bli utført (vi sender innholdet til Three.js-materialet senere). I de to første linjene definerer vi to variabler. Den første er jevn flyt tid. Uniformer overføres til både toppunkt og fragmentskader. Deretter er det varierende vec2 vUv. Varianter er grensesnittet mellom toppunktet og fragmentskader. tid vil holde tiden i millisekunder siden appen ble startet, som vi skal bruke til å beregne nye posisjoner av vertexes. I VUV Vi lagrer UV (teksturvektoren) for hvert toppunkt, slik at vi kan bruke det i fragment shader.

Deretter er det void main () erklæring. Alle shaders må ha denne funksjonen. Her passerer vi UV fra toppunktet til vår VUV og beregne toppunktets nye posisjon. Til slutt satte vi gl_Position, som faktisk setter posisjonen til toppunktet. Men også, vi må multiplisere posisjonen beregnet tidligere av projectionMatrix og modelViewMatrix, to matriser som Three.js leverer til oss. Dette er nødvendig fordi hvis vi ikke gjør dette, vil GPU ikke vurdere punktet som vi ser på toppunktet. La oss nå flytte til fragment shader.


Trinn 2: Fragment Shader

Nå er dette stedet der alt magien skjer. Fragment shaders er ansvarlige for alle de flotte spillene. Den vi skal bruke, er ganske enkel, så forvent ikke å se en scene fra Crysis 3 etter å ha brukt den. Sett inn følgende kode under vertex shader:

 

Som du kan se på toppen av shader, er det våre to variabler igjen. Du må huske på at alle variabler du bruker (unntatt de fra Three.js) må defineres i hver skygge de brukes til.

I void main () funksjon, beregner vi fargene basert på tid og UV av fragmentet (fragment shaders opererer på fragmenter, som er sammensatt av punkter, så verdiene av varierende variabler er interpolert i fragment shader). Ta det rolig med disse tallene og funksjonene (bare husk at fargeværdiene må være positive).

Til slutt setter vi inn gl_FragColor variabel som setter fragmentets farge.

Hvis du åpner nettleseren din, vil ingenting endres, fordi vi må endre materialet til objektet slik at det bruker shaders.


Trinn 3: THREE.ShaderMaterial

Dette spesielle materialet brukes når vi trenger å bruke shaders. La oss endre materialet til objektet som vi knytter til vår modell i den forrige delen av denne serien. Definer først uniformer array som vil bli brukt til å passere variabler til shaders:

 var uniformer = tid: type: "f", verdi: 0, oppløsning: type: "v2", verdi: ny THREE.Vector2, tekstur: type: "t", verdi: THREE.ImageUtils. loadTexture ('./box.png');

Deretter i loader.load definer punkts materiale og bruk det:

 var itemMaterial = nytt THREE.ShaderMaterial (uniformer: uniformer, vertexShader: document.getElementById ('cubeVertexShader'). innerHTML, fragmentShader: document.getElementById ('cubeFragmentShader'). innerHTML); item = new THREE.Mesh (new THREE.CubeGeometry (100, 10, 10), itemMaterial);

Nå, hvis du åpner nettleseren, bør du se at den røde strålen har endret farger:


Men fargene endres ikke, og masken er heller ikke animert. For å endre det, må vi oppdatere tid variabel i shaders hver gang en ramme trekkes. Gå til gjengi funksjon og legg til denne linjen etter clock.getDelta () anrop:

 uniforms.time.value + = delta * 10;

Nå, hvis du åpner nettleseren, bør du se et pent animert og fargerikt objekt:



Et ord om ytelse

Hvis vi skulle lage en slik teksturvirkning ved hjelp av for eksempel HTML5 Canvas, ville prosessen ta for mye av CPUs sykluser, noe som resulterte i lags. Men alle shaders blir henrettet på GPU, som er optimalisert for alle operasjoner på grafikk og er fokusert bare på dem. Å skille grafiske og ikke-grafiske beregninger er nøkkelen til en god utførelse av app.

Hvis du vil lage noe ekte ved hjelp av WebGL, la meg forsikre deg om at du må flytte så mye arbeid som mulig til GPU, for å gjøre søknaden jevn og lydhør.


Konklusjon

Som du kan se, bruker Three.js oss til å lage 3D-grafikk i nettleseren veldig enkelt, og resultatene er faktisk ganske bra. Men de kan bli enda bedre, ta en titt på disse eksemplene fra Three.js nettsted:

  • Hyperlapse
  • TNT for to

Med nok tid, et kreativt sinn og Three.js, kan du lage fantastiske apps som de også. Jeg vil være mer enn glad for å se dine Three.js-kreasjoner. Takk for at du leste.