iOS 8 Noțiuni de bază cu Metal

Acest tutorial vă va arăta cum să începeți cu Metal, un cadru introdus în iOS 8 care susține redarea grafică grafică 3D accelerată de GPU și încărcările de date paralele de calcul. În acest tutorial, vom arunca o privire asupra conceptelor teoretice care subliniază Metalul. Veți învăța, de asemenea, cum să creați o aplicație Metal care stabilește starea hardware necesară pentru grafică, comitează comenzi pentru execuție în GPU și gestionează tampoane, obiecte de textură și shadere precompilate.

1. Primele lucruri în primul rând

Acest tutorial presupune că sunteți familiarizat cu limba Objective-C și că aveți o experiență în OpenGL, OpenCL sau într-un grafic API comparabil.

De asemenea, este nevoie de un dispozitiv fizic cu un procesor Apple A7 sau A8. Aceasta înseamnă că veți avea nevoie de un iPhone 5S, 6 sau 6 Plus sau un iPad Air sau mini (a doua generație). Simulatorul iOS vă va oferi erori de compilare.

Acest tutorial se concentrează numai pe Metal și nu va acoperi limbajul Metal Shading. Vom crea un shader, dar vom acoperi doar operațiunile de bază pentru a interacționa cu el.

Dacă utilizați Xcode pentru prima dată, asigurați-vă că adăugați ID-ul Apple în Conturi secțiune a lui Xcode Preferințe. Acest lucru vă va asigura că nu vă confruntați cu probleme atunci când implementați o aplicație pe dispozitiv.

Xcode 6 include un șablon de proiect pentru Metal, dar pentru a vă ajuta să înțelegeți mai bine Metalul, vom crea un proiect de la zero.

Într-o notă finală, vom folosi obiectivul C în acest tutorial și este important să aveți o înțelegere de bază a acestui limbaj de programare.

2. Introducere

Pentru cei care sunteți familiarizați cu OpenGL sau OpenGL ES, Metalul este un cadru de grafică 3D de nivel inferior, dar cu un nivel mai scăzut al cheltuielilor. Spre deosebire de platformele Apple Sprite Kit sau Scene Kit cu care, în mod implicit, nu puteți interacționa cu conducta de redare, Metal are puterea absolută de a crea, controla și modifica acea conductă.

Metalul are următoarele caracteristici:

  • Cadrul oferă acces extrem de redus la procesoarele GPU A7 și A8, permițând performanțe incredibil de ridicate pentru redarea grafică sofisticată și sarcini computaționale.
  • Metalul elimină multe blocaje de performanță, cum ar fi validarea de stat costisitoare, care se găsește în API-urile grafice tradiționale.
  • Este conceput în mod explicit pentru a muta toate operațiunile de traducere și compilare de stat costisitoare din mediul de execuție și de redare.
  • Oferă shadere precompilate, obiecte de stat și programare explicită a comenzilor pentru a vă asigura că aplicația dvs. atinge cea mai înaltă performanță și eficiență posibilă pentru redarea grafică și sarcinile de calcul.
  • Cadrul a fost conceput pentru a exploata considerațiile arhitecturale moderne, cum ar fi multiprocesarea și memoria partajată.
  • Este adânc integrat cu iOS 8, chipset-urile A7 și A8 și hardware-ul Apple, creând un cadru unificat și independent.

Destul cu teoria, este timpul să înțelegem cum este construită o aplicație Metal.

3. Crearea unei aplicații metalice

O aplicație metalică este caracterizată printr-un set de pași necesari pentru prezentarea corectă a datelor pe ecran. Acești pași sunt de obicei creați în ordine și unele referințe sunt transmise de la unul la altul. Acești pași sunt:

  • accesați dispozitivul
  • creați o coadă de comandă
  • creați resurse, cum ar fi tampoane, texturi și shadere
  • creați o conductă de randare
  • creați o vizualizare

Pasul 1: Obțineți dispozitivul

Acest pas implică crearea unui MTLDevice obiect, inima unei aplicații Metal. MTLDevice clasa oferă o modalitate directă de a comunica cu driverul și hardware-ul GPU. Pentru a obține o referință la MTLDevice de exemplu, trebuie să apelați Dispozitivul implicit pentru sistem așa cum se arată mai jos. Cu această referință, aveți acces direct la hardware-ul dispozitivului.

id  mtlDevice = MTLCreateSystemDefaultDevice ();

Pasul 2: Creați o coadă de comandă

MTLCommandQueue clasa oferă o modalitate de a trimite comenzi sau instrucțiuni către GPU. Pentru a inițializa o instanță a MTLCommandQueue clasa, trebuie să utilizați MTLDevice obiect pe care l-am creat mai devreme și sunăm newCommandQueue pe ea.

id  mtlCommandQueue = [mtlDevice newCommandQueue];

Pasul 3: Creați resurse

Acest pas implică crearea obiectelor tampon, a texturilor și a altor resurse. În acest tutorial, veți crea noduri. Aceste obiecte sunt stocate pe partea server / GPU și pentru a comunica cu ele trebuie să creați o structură specifică de date care să conțină date similare cu cele disponibile în obiectul vertex.

De exemplu, dacă trebuie să transmiteți date pentru o poziție de vârf 2D, trebuie să declarați o structură de date care conține un obiect pentru acea poziție 2D. Apoi, trebuie să îl declarați atât în ​​client, în aplicația dvs. iOS, cât și în partea de server, shaderul Metal. Uitați-vă la următorul exemplu de clarificare.

typedef struct poziția GLKVector2;  YourDataStruct;

Rețineți că trebuie să importați GLKMath biblioteca din GLKit cadru, după cum se arată mai jos.

#import 

Apoi declarați un obiect cu coordonatele corecte.

Triunghiul dvs.DataStruct [3] = -.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f;

Pasul 4: Creați un canal de redare

Crearea conductei de redare este probabil cea mai dificilă etapă, deoarece trebuie să aveți grijă de mai multe inițializări și configurații, fiecare dintre acestea fiind ilustrată în diagrama următoare.

Conducta de randare este configurată utilizând două clase:

  • MTLRenderPipelineDescriptor: oferă toate stările de conducte de randare, cum ar fi pozițiile vârfurilor, culoarea, adâncimea și tampoanele de stencil, printre altele
  • MTLRenderPipelineState: versiunea compilate a MTLRenderPipelineDescriptor și care vor fi instalate pe dispozitiv

Rețineți că nu este necesar să creați toate obiectele din conducta de randare. Ar trebui doar să creați cele care să răspundă nevoilor dumneavoastră.

Următorul fragment de cod vă arată cum să creați MTLRenderPipelineDescriptor obiect.

MTLRenderPipelineDescriptor * mtlRenderPipelineDescriptor = [MTLRenderPipelineDescriptor nou]; 

În acest moment, ați creat descriptorul, dar tot trebuie să îl configurați cu cel puțin formatul pixelilor. Aceasta este ceea ce facem în următorul bloc de coduri.

mtlRenderPipelineDescriptor.colorAtașamente [0] .pixelFormat = MTLPixelFormatBGRA8Unorm;

Pentru aplicațiile mai avansate, trebuie de asemenea să setați versiunea implicită și shaderele fragmentului după cum se arată mai jos.

id  lib = [mtlDevice newDefaultLibrary]; mtlRenderPipelineDescriptor.vertexFunction = [lib nouFunctionWithName: @ "SomeVertexMethodName"]; mtlRenderPipelineDescriptor.fragmentFunction = [lib newFunctionWithName: @ "SomeFragmentMethodName"];

newFunctionWithName metoda caută fișierul sursă de metale, căutând SomeVertexMethodName metodă. Numele shader-ului în sine nu este important, deoarece căutarea se face direct prin numele de metode. Aceasta înseamnă că trebuie să definiți metode unice pentru operațiile de shader unice. Vom arăta mai adânc în Metal Shaders mai târziu.

Cu MTLRenderPipelineDescriptor obiect creat și configurat, următorul pas este crearea și definirea MTLRenderPipelineState prin trecerea în nou creat MTLRenderPipelineDescriptor obiect.

NSError * eroare = [[NSError alloc] init]; id  mtlRenderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor: eroare mtlRenderPipelineDescriptor: & eroare];

Pasul 5: Creați o vizualizare

Pentru a crea o vizualizare Metal, trebuie să faceți subclasa UIView și suprascrie layerClass așa cum se arată mai jos.

+(id) layerClass retur [clasa CAMetalLayer]; 

În acest tutorial, vom examina un alt mod de a crea un CAMetalLayer clasa care oferă dezvoltatorului mai mult control asupra caracteristicilor și configurației stratului.

4. Desenarea unei aplicații metalice

Acum că am inițializat obiectele necesare, trebuie să începem să desenăm ceva pe ecran. La fel ca inițializarea, trebuie să urmați o serie de pași:

  • obțineți tampon de comandă
  • setați o trecere de redare
  • a desena.
  • să se angajeze la tampon de comandă

Pasul 1: Obțineți bufferul de comandă

Pasul inițial este crearea unui obiect care stochează o listă serială de comenzi pentru a executa dispozitivul. Creați a MTLCommandBuffer obiect și adăugați comenzi care vor fi executate secvențial de GPU. Următorul fragment de cod arată cum se creează un buffer de comandă. Noi folosim MTLCommandQueue obiect creat mai devreme.

id  mtlCommandBuffer = [mtlCommandQueue commandBuffer];

Pasul 2: Începeți un Pass Render

În Metal, configurația de randare este complexă și trebuie să indicați în mod explicit momentul în care începe procesul de render și când se termină. Trebuie să definiți configurațiile framebuffer în față pentru ca iOS să configureze hardware-ul corespunzător pentru configurația respectivă.

Pentru cei familiarizați cu OpenGL și OpenGL ES, acest pas este similar, deoarece framebuffer are aceleași proprietăți, Atașarea culorilor (0 până la 3), Adâncime, și vopsi configurații. Puteți vedea o reprezentare vizuală a acestui pas în diagrama de mai jos.

Mai întâi trebuie să creați o textură pentru a face. Textura este creată din CAMetalDrawable clasa și utilizează nextDrawable pentru a extrage următoarea textură pentru a desena în listă.

id  frameDrawable; frameDrawable = [renderLayer nextDrawable];

Acest nextDrawable apelul poate fi și va fi blocarea aplicației dvs., deoarece vă poate bloca cu ușurință aplicația. CPU-ul și GPU-ul pot fi desincronizate, iar celălalt trebuie să aștepte cealaltă, ceea ce poate provoca o declarație bloc. Există mecanisme sincrone care pot și trebuie întotdeauna implementate pentru a rezolva aceste probleme, dar nu le voi acoperi în acest tutorial introductiv.

Acum că aveți o textura pe care să o faceți, trebuie să creați un MTLRenderPassDescriptor obiect pentru a stoca informațiile despre framebuffer și textură. Uitați-vă la următorul fragment de cod pentru a vedea cum funcționează acest lucru.

MTLRenderPassDescriptor * mtlRenderPassDescriptor; mtlRenderPassDescriptor = [MTLRenderPassDescriptor nou]; mtlRenderPassDescriptor.colorAttachments [0] .texture = frameDrawable.texture; mtlRenderPassDescriptor.colorAtașamente [0] .loadAction = MTLLoadActionClear; mtlRenderPassDescriptor.colorAttachments [0] .clearColor = MTLClearColorMake (0,75, 0,25, 1,0, 1,0);

Primul pas stabilește textura care trebuie desenată. Al doilea defineste o actiune specifica de luat, in acest caz curatarea texturii si prevenirea incarcarii continutului texturii in cache-ul GPU-ului. Pasul final modifică culoarea de fundal la o anumită culoare.

Pasul 3: Desenați

Cu framebuffer-ul și textura configurată, este timpul să creați o MTLRenderCommandEncoder instanță. MTLRenderCommandEncoder clasa este responsabilă pentru interacțiunile tradiționale cu ecranul și poate fi văzută ca un container pentru o stare de redare grafică. De asemenea, vă traduce codul într-un format de comandă specific pentru hardware care va fi executat de dispozitiv.

id  renderCommand = [mtlCommandBuffer renderCommandEncoderWithDescriptor: mtlRenderPassDescriptor]; // Setați MTLRenderPipelineState // Desenați obiecte aici [renderCommand endEncoding];

Pasul 4: Angajați la Bufferul de comandă

Acum avem un tampon și instrucțiuni care așteaptă în memorie. Următorul pas este să comiteți comenzile la tamponul de comandă și să vedeți graficul desenat pe ecran. Rețineți că GPU-ul va executa numai codul pe care îl obligați în mod specific pentru efect. Următoarele rânduri de cod vă permit să programați framebuffer-ul și să transferați tamponul de comandă către GPU.

[mtlCommandBuffer presentDrawable: frameDrawable]; [mtlCommandBuffer commit];

În acest moment, ar trebui să aveți o idee generală despre modul în care este structurată o aplicație Metal. Cu toate acestea, pentru a înțelege corect toate acestea, trebuie să o faceți singur. Acum este momentul să codificați prima aplicație Metal.

5. Crearea unei aplicații metalice

Porniți Xcode 6 și alegeți Nou> Proiect ... de la Fişier meniul. Selectați Vizualizare individuală din lista de șabloane și alegeți un nume de produs. A stabilit Obiectiv-C ca limba și selectați iPhone de la Dispozitive meniul.

Deschis ViewController.m și adăugați următoarele declarații de import în partea de sus.

#import  #import 

De asemenea, trebuie să adăugați Metal și QuartzCore cadrelor în Cadrele și bibliotecile asociate secțiune a obiectivului Construiți faze. De acum înainte, atenția dvs. ar trebui să vizeze dosarul de punere în aplicare a ViewController clasă.

6. Crearea structurii metalice

După cum am menționat mai devreme, prima dvs. sarcină este să setați și să inițializați obiectele de bază utilizate în întreaga aplicație. În următorul fragment de cod, declarăm un număr de variabile de instanță. Acestea ar trebui să pară familiare dacă ați citit prima parte a acestui tutorial.

@implementation ViewController id  mtlDevice; id  mtlCommandQueue; MTLRenderPassDescriptor * mtlRenderPassDescriptor; CAMetalLayer * metalLayer; id  frameDrawable; CADisplayLink * displayLink; 

În controlerul de vizualizare viewDidLoad , inițializăm MTLDevice și CommandQueue instanțe.

mtlDevice = MTLCreateSystemDefaultDevice (); mtlCommandQueue = [mtlDevice newCommandQueue];

Acum puteți interacționa cu dispozitivul și puteți crea cozi de comandă. Acum este timpul să configurați CAMetalLayer obiect. Ta CAMetalLayer stratul trebuie să aibă o configurație specifică, în funcție de dispozitiv, de formatul pixel și de dimensiunea cadrului. De asemenea, trebuie să specificați că va folosi numai framebuffer și că ar trebui adăugat la stratul curent.

Dacă aveți o problemă de configurare CAMetalLayer obiect, atunci fragmentul de cod de mai jos vă va ajuta în acest scop.

metalLayer = [stratul CAMetalLayer]; [metalLayer setDevice: mtlDevice]; [metalLayer setPixelFormat: MTLPixelFormatBGRA8Unorm]; metalLayer.framebufferOnly = DA; [metalLayer setFrame: self.view.layer.frame]; [auto.view.layer addSublayer: metalLayer];

De asemenea, trebuie să setați opacitatea vizuală, culoarea de fundal și factorul de scală a conținutului. Acest lucru este ilustrat în următorul fragment de cod.

[self.view setOpaque: YES]; [auto.view setBackgroundColor: nul]; [auto.view setContentScaleFactor: [UIScreen mainScreen] .scale];

Singurul pas rămas este de a face ceva pe ecran. Inițializați CADisplayLink, trecerea de sine ca țintă și @selector (renderScene) ca selector. În cele din urmă, adăugați CADisplayLink obiecte față de bucla de alergare curentă.

displayLink = [afișare CADisplayLinkLinkWithTarget: SELECTOR SELECTOR: @selector (renderScene)]; [displayLink addToRunLoop: [NSRunLoop currentRunLoop] pentruMode: NSDefaultRunLoopMode];

Aceasta este ceea ce a fost finalizat viewDidLoad metoda ar trebui să arate ca.

- (vid) viewDidLoad [super viewDidLoad]; mtlDevice = MTLCreateSystemDefaultDevice (); mtlCommandQueue = [mtlDevice newCommandQueue]; metalLayer = [stratul CAMetalLayer]; [metalLayer setDevice: mtlDevice]; [metalLayer setPixelFormat: MTLPixelFormatBGRA8Unorm]; metalLayer.framebufferOnly = DA; [metalLayer setFrame: self.view.layer.frame]; [auto.view.layer addSublayer: metalLayer]; [self.view setOpaque: YES]; [auto.view setBackgroundColor: nul]; [auto.view setContentScaleFactor: [UIScreen mainScreen] .scale]; displayLink = [afișare CADisplayLinkLinkWithTarget: SELECTOR SELECTOR: @selector (renderScene)]; [displayLink addToRunLoop: [NSRunLoop currentRunLoop] pentruMode: NSDefaultRunLoopMode]; 

Dacă construiți proiectul, veți observa că Xcode ne dă un avertisment. Încă mai trebuie să punem în aplicare renderScene metodă.

renderScene metoda este executată în fiecare cadru. Există mai multe obiecte care trebuie inițializate pentru fiecare cadru nou, cum ar fi MTLCommandBuffer și MTLRenderCommandEncoder obiecte.

Pașii pe care trebuie să le luăm pentru a face un cadru sunt:

  • creeaza o MTLCommandBuffer obiect
  • inițializați o CAMetalDrawable obiect
  • inițializați o MTLRenderPassDescriptor obiect
  • configurați textură, loadAction, clearColor, și storeAction proprietățile MTLRenderPassDescriptor obiect
  • creaza un nou MTLRenderCommandEncoder obiect
  • prezentați tamponul de comandă care poate fi remorcat și activat

Simțiți-vă liber să revizuiți ceea ce am văzut până acum pentru a rezolva această provocare pe cont propriu. Dacă doriți să continuați cu acest tutorial, atunci aruncați o privire la soluția prezentată mai jos.

- (void) renderScene id mtlCommandBuffer = [mtlCommandQueue commandBuffer]; în timp ce (! frameDrawable) frameDrawable = [metalLayer nextDrawable];  dacă (! mtlRenderPassDescriptor) mtlRenderPassDescriptor = [MTLRenderPassDescriptor nou]; mtlRenderPassDescriptor.colorAttachments [0] .texture = frameDrawable.texture; mtlRenderPassDescriptor.colorAtașamente [0] .loadAction = MTLLoadActionClear; mtlRenderPassDescriptor.colorAttachments [0] .clearColor = MTLClearColorMake (0,75, 0,25, 1,0, 1,0); mtlRenderPassDescriptor.colorAttachments [0] .storeAction = MTLStoreActionStore; id  renderCommand = [mtlCommandBuffer renderCommandEncoderWithDescriptor: mtlRenderPassDescriptor]; // Desenați obiectele aici // setați MTLRenderPipelineState ... [renderCommand endEncoding]; [mtlCommandBuffer presentDrawable: frameDrawable]; [mtlCommandBuffer commit]; mtlRenderPassDescriptor = zero; frameDrawable = zero; 

De asemenea, trebuie să implementăm controlerul de vizualizare dealloc în care ne invalidăm DisplayLink obiect. Am setat mtlDevice și mtlCommandQueue obiecte pentru zero.

-(void) dealloc [displayLink invalidate]; mtlDevice = nil; mtlCommandQueue = nil; 

7. Desenarea unui triunghi

Acum aveți o aplicație Metal foarte fundamentală. Este timpul să adăugați prima dvs. primitivă grafică, un triunghi. Primul pas este crearea unei structuri pentru triunghi.

typedef struct poziția GLKVector2; Triunghi;

Nu uitați să adăugați o declarație de import pentru GLKMath bibliotecă în partea de sus a ViewController.m.

#import 

Pentru a face triunghiul, trebuie să creați a MTLRenderPipelineDescriptor obiect și a MTLRenderPipelineState obiect. În plus, fiecare obiect care este tras pe ecran aparține MTLBuffer clasă.

MTLRenderPipelineDescriptor * renderPipelineDescriptor; id  renderPipelineState; id  obiect;

Cu aceste variabile de instanță declarate, ar trebui să le inițializați acum în viewDidLoad așa cum am explicat anterior.

renderPipelineDescriptor = [MTLRenderPipelineDescriptor nou]; renderPipelineDescriptor.colorAttachments [0] .pixelFormat = MTLPixelFormatBGRA8Unorm;

Pentru a umbla triunghiul, vom avea nevoie de shadere de metal. Shaderele de metal trebuie să fie atribuite MTLRenderPipelineDescriptor obiect și încapsulate printr-o MTLLibrary protocol. Poate suna complex, dar trebuie doar să utilizați următoarele linii de cod:

id  lib = [mtlDevice newDefaultLibrary]; renderPipelineDescriptor.vertexFunction = [lib newFunctionWithName: @ "VertexColor"]; renderPipelineDescriptor.fragmentFunction = [lib newFunctionWithName: @ "FragmentColor"]; renderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor: eroare renderPipelineDescriptor: nul];

Prima linie creează un obiect care este conform cu MTLLibrary protocol. În al doilea rând, îi spunem bibliotecii ce metodă trebuie invocată în interiorul shader-ului pentru a acționa trecerea vertexului în interiorul conductei de randare. În a treia linie, repetăm ​​acest pas la nivelul pixelilor, fragmentele. În cele din urmă, în ultima linie vom crea a MTLRenderPipelineState obiect.

În Metal, puteți defini coordonatele sistemului, dar în acest tutorial veți folosi sistemul de coordonate implicit, adică coordonatele centrului ecranului (0,0).

În următorul bloc de coduri, vom crea un obiect triunghi cu trei coordonate, (-5f, 0,0f), (0,5f, 0,0f), (0,0f, 0,5f).

Triunghi triunghi [3] = -.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f;

Apoi adăugăm triunghiul la obiect, care creează un buffer pentru triunghi.

obiect = [mtlDevice newBufferWithBytes: lungime triunghi: sizeof (Triangle [3]): MTLResourceOptionCPUCacheModeDefault];

Aceasta este ceea ce a fost finalizat viewDidLoad metoda ar trebui să arate ca.

- (vid) viewDidLoad [super viewDidLoad]; mtlDevice = MTLCreateSystemDefaultDevice (); mtlCommandQueue = [mtlDevice newCommandQueue]; metalLayer = [stratul CAMetalLayer]; [metalLayer setDevice: mtlDevice]; [metalLayer setPixelFormat: MTLPixelFormatBGRA8Unorm]; metalLayer.framebufferOnly = DA; [metalLayer setFrame: self.view.layer.frame]; [auto.view.layer addSublayer: metalLayer]; [self.view setOpaque: YES]; [auto.view setBackgroundColor: nul]; [auto.view setContentScaleFactor: [UIScreen mainScreen] .scale]; // Creați o conductă reutilizabilă renderPipelineDescriptor = [MTLRenderPipelineDescriptor new]; renderPipelineDescriptor.colorAttachments [0] .pixelFormat = MTLPixelFormatBGRA8Unorm; id  lib = [mtlDevice newDefaultLibrary]; renderPipelineDescriptor.vertexFunction = [lib newFunctionWithName: @ "VertexColor"]; renderPipelineDescriptor.fragmentFunction = [lib newFunctionWithName: @ "FragmentColor"]; renderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor: eroare renderPipelineDescriptor: nul]; Triunghi triunghi [3] = -.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f; obiect = [mtlDevice newBufferWithBytes: lungime triunghi: sizeof (Triangle [3]): MTLResourceOptionCPUCacheModeDefault]; displayLink = [afișare CADisplayLinkLinkWithTarget: SELECTOR SELECTOR: @selector (renderScene)]; [displayLink addToRunLoop: [NSRunLoop currentRunLoop] pentruMode: NSDefaultRunLoopMode]; 

 viewDidLoad metoda este completă, dar lipsește ultimul pas, creând shaderele.

8. Crearea shaderelor

Pentru a crea un shader de metal, selectați Nou> Fișier ...  de la Fişier meniu, alegeți Sursă > Fișier metalic de la iOS și denumiți-o MyShader. Xcode va crea apoi un fișier nou pentru dvs., MyShader.metal.

În partea de sus, ar trebui să vedeți următoarele două linii de cod. Primul include Bibliotecă standard metalică în timp ce al doilea utilizează metal Spațiu de nume.

#include  folosind spațiul din spațiul de nume;

Primul pas este să copiați structura triunghiului la shader. Shaderele sunt de obicei împărțite în două operații diferite, vertex și pixeli (fragmente). Primul este legat de poziția vârfului, în timp ce al doilea este legat de culoarea finală a acelui vârf și de toate pozițiile pixelilor din interiorul poligonului. Puteți să vă uitați în acest fel, primul va rasteriza poligonul, pixelii poligonului, iar al doilea va umbri aceiași pixeli.

Deoarece au nevoie să comunice într-un mod unidirecțional, de la vârf la fragment, este mai bine să creeze o structură pentru datele care vor fi transmise. În acest caz, vom trece doar poziția.

typedef struct float4 poziție [[poziție]];  TriangleOutput;

Acum, să creăm metodele vertex și fragment. Amintiți-vă când ați programat RenderPipelineDescriptor obiect atât pentru vârf și fragment? Ai folosit newFunctionWithName metoda, trecând într-un NSString obiect. Șirul este numele metodei pe care o numiți în interiorul shaderului. Aceasta înseamnă că trebuie să declarați două metode cu aceste nume, VertexColor și FragmentColor.

Ce inseamna asta? Puteți crea shaderele și le puteți numi după cum doriți, dar trebuie să apelați metodele exact așa cum le declarați și ar trebui să aibă nume unice.

În interiorul shaderelor, adăugați următorul bloc de coduri.

vertex TriangleOutput VertexColor (const constă Triangle * Vertices [[buffer (0)]], const uint index [[vertex_id]]) TriangleOutput out; out.position = float4 (Vertices [index] .poziție, 0.0, 1.0); retur;  fragment half4 FragmentColor (void) returnează jumătate4 (1.0, 0.0, 0.0, 1.0); 

VertexColor metoda va primi datele stocate în poziție 0 din memoria tampon (memoria alocată) și vertex_id a vârfului. Deoarece am declarat un triunghi cu trei vârfuri, vertex_id va fi 0, 1, și 2. Se emite a TriangleOutput obiect care este primit automat de către FragmentColor. În cele din urmă, acesta va umbri fiecare pixel în interiorul celor trei noduri folosind o culoare roșie.

Asta e. Construiți și rulați aplicația dvs. și bucurați-vă de prima dvs. aplicație de metal 60fps.

9. Resurse externe

Dacă doriți să aflați mai multe despre cadrul metalic și cum funcționează, puteți verifica câteva alte resurse:

  • WWDC 2014 (Lucrări cu secțiuni metalice)
  • Referința cadrului metalic
  • Ghid de programare metal

Concluzie

Aceasta incheie tutorialul nostru introductiv pe noul cadru metalic. Dacă aveți întrebări sau comentarii, nu ezitați să renunțați la o linie în comentarii.

Cod