iOS 8 Premiers pas avec le métal

Ce didacticiel vous montrera comment démarrer avec Metal, un framework introduit dans iOS 8 qui prend en charge les charges de travail de rendu graphique 3D accéléré par GPU et de calcul parallèle de données. Dans ce tutoriel, nous allons examiner les concepts théoriques qui sous-tendent le métal. Vous apprendrez également à créer une application Metal qui définit l'état matériel requis pour les graphiques, valide les commandes à exécuter dans le GPU et gère les tampons, les objets de texture et les shaders précompilés..

1. Premières choses d'abord

Ce tutoriel suppose que vous maîtrisiez bien le langage Objective-C et que vous maîtrisiez bien OpenGL, OpenCL ou une API graphique comparable..

Il nécessite également un périphérique physique doté d'un processeur Apple A7 ou A8. Cela signifie que vous aurez besoin d'un iPhone 5S, 6 ou 6 Plus, d'un iPad Air ou d'un mini (2e génération). Le simulateur iOS vous donnera des erreurs de compilation.

Ce didacticiel est uniquement axé sur le métal et ne couvre pas le langage d’ombrage des métaux. Nous allons créer un shader, mais nous ne couvrirons que les opérations de base pour interagir avec lui.

Si vous utilisez Xcode pour la première fois, assurez-vous d’ajouter votre identifiant Apple à la Comptes section de Xcode Préférences. Cela garantira que vous ne rencontrez pas de problèmes lors du déploiement d'une application sur votre appareil.

Xcode 6 inclut un modèle de projet pour Metal, mais pour vous aider à mieux comprendre Metal, nous allons créer un projet à partir de zéro..

Sur une note finale, nous utiliserons Objective-C dans ce tutoriel et il est important que vous ayez une compréhension de base de ce langage de programmation..

2. Introduction

Pour ceux d'entre vous qui connaissent OpenGL ou OpenGL ES, Metal est un framework graphique 3D de bas niveau, mais avec un temps système réduit. Contrairement aux frameworks Sprite Kit ou Scene Kit d'Apple avec lesquels, par défaut, vous ne pouvez pas interagir avec le pipeline de rendu, Metal dispose du pouvoir absolu de créer, contrôler et modifier ce pipeline..

Le métal présente les caractéristiques suivantes:

  • La structure offre un accès extrêmement léger aux GPU A7 et A8, offrant des performances incroyablement élevées pour le rendu graphique sophistiqué et les tâches de calcul..
  • Metal élimine de nombreux goulots d'étranglement liés aux performances, tels que la validation d'état coûteuse que l'on trouve dans les API graphiques traditionnelles.
  • Il est explicitement conçu pour déplacer toutes les opérations de compilation et de traduction d'état coûteuses hors de l'environnement d'exécution et de rendu..
  • Il fournit des shaders précompilés, des objets d'état et une planification explicite des commandes pour garantir à votre application les performances et l'efficacité les plus élevées possibles pour le rendu graphique et les tâches de calcul..
  • Le cadre a été conçu pour exploiter des considérations architecturales modernes, telles que le multitraitement et la mémoire partagée..
  • Il est profondément intégré à iOS 8, aux jeux de puces A7 et A8 et au matériel Apple, créant ainsi un cadre unifié et indépendant..

Assez avec la théorie, il est temps de comprendre comment une application Metal est construite.

3. Créer une application métallique

Une application Métal est caractérisée par un ensemble d'étapes requises pour présenter correctement les données à l'écran. Ces étapes sont généralement créées dans l’ordre et certaines références sont transmises de l’une à l’autre. Ces étapes sont:

  • obtenir l'appareil
  • créer une file d'attente de commandes
  • créer des ressources, telles que des tampons, des textures et des shaders
  • créer un pipeline de rendu
  • créer une vue

Étape 1: obtenir le périphérique

Cette étape implique la création d’un MTLDevice objet, le coeur d'une application Metal. le MTLDevice class fournit un moyen direct de communiquer avec le pilote et le matériel du processeur graphique. Pour obtenir une référence à un MTLDevice par exemple, vous devez appeler le Dispositif par défaut du système comme indiqué ci-dessous. Avec cette référence, vous avez un accès direct au matériel de l'appareil.

identifiant  mtlDevice = MTLCreateSystemDefaultDevice ();

Étape 2: créer une file d'attente de commandes

le MTLCommandQueue La classe fournit un moyen de soumettre des commandes ou des instructions au GPU. Pour initialiser une instance du MTLCommandQueue classe, vous devez utiliser le MTLDevice objet que nous avons créé plus tôt et appeler le newCommandQueue méthode sur elle.

identifiant  mtlCommandQueue = [mtlDevice newCommandQueue];

Étape 3: Créer des ressources

Cette étape implique la création de vos objets tampons, textures et autres ressources. Dans ce tutoriel, vous allez créer des sommets. Ces objets sont stockés côté serveur / GPU et pour communiquer avec eux, vous devez créer une structure de données spécifique, qui doit contenir des données similaires à celles disponibles dans l'objet sommet..

Par exemple, si vous devez transmettre des données pour une position de sommet 2D, vous devez déclarer une structure de données contenant un objet pour cette position 2D. Ensuite, vous devez le déclarer dans le client, votre application iOS, et côté serveur, le Metal Shader. Regardez l'exemple suivant pour plus de précisions.

typedef struct position GLKVector2;  YourDataStruct;

Notez que vous devez importer le GLKMath bibliothèque de la GLKit cadre comme indiqué ci-dessous.

#importation 

Vous déclarez ensuite un objet avec les coordonnées correctes.

Triangle YourDataStruct [3] = -.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f;

Étape 4: Créer un pipeline de rendu

La création du pipeline de rendu est probablement l'étape la plus délicate, car vous devez prendre en charge plusieurs initialisations et configurations, chacune d'elles étant illustrée dans le diagramme suivant..

Le pipeline de rendu est configuré à l'aide de deux classes:

  • MTLRenderPipelineDescriptor: fournit tous les états de votre pipeline de rendu, tels que les positions des sommets, la couleur, la profondeur et les tampons de gabarit, entre autres
  • MTLRenderPipelineState: la version compilée de MTLRenderPipelineDescriptor et qui sera déployé sur l'appareil

Notez qu'il n'est pas nécessaire de créer tous les objets de pipeline de rendu. Vous devriez juste créer ceux qui répondent à vos besoins.

L’extrait de code suivant vous montre comment créer le MTLRenderPipelineDescriptor objet.

MTLRenderPipelineDescriptor * mtlRenderPipelineDescriptor = [MTLRenderPipelineDescriptor new]; 

À ce stade, vous avez créé le descripteur, mais vous devez toujours le configurer avec au moins le format de pixel. C'est ce que nous faisons dans le bloc de code suivant.

mtlRenderPipelineDescriptor.colorAttachments [0] .pixelFormat = MTLPixelFormatBGRA8Unorm;

Pour des applications plus avancées, vous devez également définir les shaders de vertex et de fragment par défaut, comme indiqué ci-dessous..

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

le newFunctionWithName méthode recherche dans votre fichier source Metal, à la recherche du SomeVertexMethodName méthode. Le nom du shader lui-même n'est pas important car la recherche s'effectue directement à travers les noms de méthodes. Cela signifie que vous devez définir des méthodes uniques pour des opérations de shader uniques. Nous examinerons plus en profondeur les shaders métalliques plus tard.

Avec le MTLRenderPipelineDescriptor objet créé et configuré, l'étape suivante consiste à créer et à définir le MTLRenderPipelineState en passant dans le nouveau créé MTLRenderPipelineDescriptor objet.

NSError * error = [[NSError alloc] init]; identifiant  mtlRenderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor: erreur mtlRenderPipelineDescriptor: & error];

Étape 5: Créer une vue

Pour créer une vue Metal, vous devez créer une sous-classe. UIView et remplacer le layerClass méthode comme indiqué ci-dessous.

+(id) layerClass return [classe CAMetalLayer]; 

Dans ce tutoriel, nous examinerons une autre façon de créer un CAMetalLayer classe qui donne au développeur plus de contrôle sur les caractéristiques et la configuration de la couche.

4. Dessiner une application en métal

Maintenant que nous avons initialisé les objets nécessaires, nous devons commencer à dessiner quelque chose sur l’écran. Tout comme l'initialisation, vous devez suivre un certain nombre d'étapes:

  • obtenir le tampon de commande
  • définir une passe de rendu
  • dessiner.
  • commettre à la mémoire tampon de commande

Étape 1: Obtenir le tampon de commande

La première étape consiste à créer un objet qui stocke une liste série de commandes à exécuter par le périphérique. Vous créez un MTLCommandBuffer objet et ajouter des commandes qui seront exécutées séquentiellement par le GPU. L'extrait de code suivant montre comment créer un tampon de commande. Nous utilisons le MTLCommandQueue objet que nous avons créé plus tôt.

identifiant  mtlCommandBuffer = [mtlCommandQueue commandBuffer];

Étape 2: commencez un passe rendu

Dans Metal, la configuration du rendu est complexe et vous devez indiquer explicitement quand le rendu du rendu commence et quand il se termine. Vous devez définir les configurations de framebuffer à l’avance pour que iOS puisse configurer le matériel correctement pour cette configuration spécifique..

Pour ceux qui connaissent OpenGL et OpenGL ES, cette étape est similaire car le framebuffer a les mêmes propriétés., Attachement de couleur (0 à 3), Profondeur, et Pochoir configurations. Vous pouvez voir une représentation visuelle de cette étape dans le diagramme ci-dessous.

Vous devez d’abord créer une texture à rendre. La texture est créée à partir du CAMetalDrawable classe et utilise le nextDrawable méthode pour récupérer la prochaine texture à dessiner dans la liste.

identifiant  frameDrawable; frameDrawable = [renderLayer nextDrawable];

Ce nextDrawable appeler peut et serait le goulot d’étranglement de votre application car il peut facilement bloquer votre application. La CPU et le GPU peuvent être désynchronisés et l'un doit attendre l'autre, ce qui peut provoquer une instruction de blocage. Il existe des mécanismes synchrones qui peuvent, et devraient toujours, être mis en œuvre pour résoudre ces problèmes, mais je ne les couvrirai pas dans ce didacticiel d'introduction..

Maintenant que vous avez une texture à rendre, vous devez créer un MTLRenderPassDescriptor objet pour stocker les informations de framebuffer et de texture. Jetez un coup d'œil à l'extrait de code suivant pour voir comment cela fonctionne..

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

La première étape configure la texture à dessiner. La seconde définit une action spécifique à effectuer, dans ce cas, effacer la texture et empêcher le chargement du contenu de cette texture dans le cache du GPU. La dernière étape change la couleur de fond en une couleur spécifique.

Étape 3: dessiner

Avec le framebuffer et la texture configurés, il est temps de créer un MTLRenderCommandEncoder exemple. le MTLRenderCommandEncoder La classe est responsable des interactions traditionnelles avec l'écran et peut être considérée comme un conteneur pour un état de rendu graphique. Il traduit également votre code en un format de commande spécifique au matériel qui sera exécuté par le périphérique..

identifiant  renderCommand = [mtlCommandBuffer renderCommandEncoderWithDescriptor: mtlRenderPassDescriptor]; // Définit MTLRenderPipelineState // Dessine des objets ici [renderCommand endEncoding];

Étape 4: S'engager dans le tampon de commande

Nous avons maintenant un tampon et des instructions en attente dans la mémoire. L'étape suivante consiste à valider les commandes dans le tampon de commandes et à visualiser les graphiques dessinés à l'écran. Notez que le GPU n'exécutera que le code que vous avez spécifiquement validé pour l'effet. Les lignes de code suivantes vous permettent de planifier votre framebuffer et de valider le tampon de commande dans le GPU.

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

À ce stade, vous devriez avoir une idée générale de la structure d’une application Metal. Cependant, pour bien comprendre tout cela, vous devez le faire vous-même. Il est maintenant temps de coder votre première application Metal.

5. Créer une application métallique

Lancez Xcode 6 et choisissez Nouveau> Projet… du Fichier menu. Sélectionner Application à vue unique dans la liste des modèles et choisissez un nom de produit. Ensemble Objectif c comme langue et sélectionnez iPhone du Dispositifs menu.

Ouvrir ViewController.m et ajoutez les instructions d'importation suivantes en haut.

#importation  #importation 

Vous devez également ajouter le Métal et QuartzCore cadres dans le Cadres et bibliothèques liés section de la cible Phases de construction. À partir de maintenant, votre attention devrait être ciblée sur le dossier de mise en œuvre du ViewController classe.

6. Création de la structure métallique

Comme je l'ai mentionné précédemment, votre première tâche consiste à définir et à initialiser les objets principaux utilisés dans l'ensemble de l'application. Dans l'extrait de code suivant, nous déclarons un certain nombre de variables d'instance. Cela devrait vous paraître familier si vous avez lu la première partie de ce tutoriel..

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

Dans le contrôleur de vue viewDidLoad méthode, on initialise le MTLDevice et CommandQueue les instances.

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

Vous pouvez maintenant interagir avec votre appareil et créer des files d'attente de commandes. Il est maintenant temps de configurer le CAMetalLayer objet. Votre CAMetalLayer La couche doit avoir une configuration spécifique en fonction du périphérique, du format de pixel et de la taille de trame. Vous devez également spécifier qu'il utilisera uniquement le framebuffer et qu'il devra être ajouté au calque actuel..

Si vous avez un problème pour configurer le CAMetalLayer objet, l'extrait de code suivant vous aidera avec cette opération..

metalLayer = [couche CAMetalLayer]; [metalLayer setDevice: mtlDevice]; [metalLayer setPixelFormat: MTLPixelFormatBGRA8Unorm]; metalLayer.framebufferOnly = YES; [metalLayer setFrame: self.view.layer.frame]; [self.view.layer addSublayer: metalLayer];

Vous devez également définir l'opacité de la vue, la couleur d'arrière-plan et le facteur d'échelle du contenu. Ceci est illustré dans l'extrait de code suivant.

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

La seule étape qui reste consiste à rendre quelque chose à l'écran. Initialiser le CADisplayLink, en passant soi comme cible et @selector (renderScene) en tant que sélecteur. Enfin, ajoutez le CADisplayLink objet à la boucle courante.

displayLink = [CADisplayLink displayLinkWithTarget: sélecteur automatique: @selector (renderScene)]; [displayLink addToRunLoop: [NSRunLoop currentRunLoop] pourMode: NSDefaultRunLoopMode];

C'est ce que l'achèvement viewDidLoad la méthode devrait ressembler à.

- (void) viewDidLoad [super viewDidLoad]; mtlDevice = MTLCreateSystemDefaultDevice (); mtlCommandQueue = [mtlDevice newCommandQueue]; metalLayer = [couche CAMetalLayer]; [metalLayer setDevice: mtlDevice]; [metalLayer setPixelFormat: MTLPixelFormatBGRA8Unorm]; metalLayer.framebufferOnly = YES; [metalLayer setFrame: self.view.layer.frame]; [self.view.layer addSublayer: metalLayer]; [auto.view setOpaque: YES]; [self.view setBackgroundColor: nil]; [self.view setContentScaleFactor: [UIScreen mainScreen] .scale]; displayLink = [CADisplayLink displayLinkWithTarget: sélecteur automatique: @selector (renderScene)]; [displayLink addToRunLoop: [NSRunLoop currentRunLoop] pourMode: NSDefaultRunLoopMode]; 

Si vous construisez le projet, vous remarquerez que Xcode nous envoie un avertissement. Nous devons encore mettre en œuvre le renderScene méthode.

le renderScene La méthode est exécutée à chaque image. Plusieurs objets doivent être initialisés pour chaque nouvelle image, tels que le MTLCommandBuffer et MTLRenderCommandEncoder objets.

Les étapes à suivre pour rendre un cadre sont les suivantes:

  • créer un MTLCommandBuffer objet
  • initialiser un CAMetalDrawable objet
  • initialiser un MTLRenderPassDescriptor objet
  • configurer le texture, loadAction, clearColor, et storeAction propriétés du MTLRenderPassDescriptor objet
  • créer un nouveau MTLRenderCommandEncoder objet
  • présenter le dessinable et commettre le tampon de commande

N'hésitez pas à revenir sur ce que nous avons vu jusqu'à présent pour résoudre ce défi par vous-même. Si vous souhaitez continuer avec ce tutoriel, jetez un coup d'œil à la solution ci-dessous..

- (void) renderScene id mtlCommandBuffer = [mtlCommandQueue commandBuffer]; while (! frameDrawable) frameDrawable = [metalLayer nextDrawable];  if (! mtlRenderPassDescriptor) mtlRenderPassDescriptor = [MTLRenderPassDescriptor new]; mtlRenderPassDescriptor.colorAttachments [0] .texture = frameDrawable.texture; mtlRenderPassDescriptor.colorAttachments [0] .loadAction = MTLLoadActionClear; mtlRenderPassDescriptor.colorAttachments [0] .clearColor = MTLClearColorMake (0,75, 0,25, 1,0, 1,0); mtlRenderPassDescriptor.colorAttachments [0] .storeAction = MTLStoreActionStore; identifiant  renderCommand = [mtlCommandBuffer renderCommandEncoderWithDescriptor: mtlRenderPassDescriptor]; // Dessine des objets ici // définit MTLRenderPipelineState… [renderCommand endEncoding]; [mtlCommandBuffer presentDrawable: frameDrawable]; [mtlCommandBuffer commit]; mtlRenderPassDescriptor = nil; frameDrawable = nil; 

Nous devons également implémenter le contrôleur de vue dealloc méthode dans laquelle on invalide la displayLink objet. Nous avons mis le mtlDevice et mtlCommandQueue objets à néant.

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

7. Tracer un triangle

Vous avez maintenant une application Metal très basique. Il est temps d'ajouter votre première primitive graphique, un triangle. La première étape consiste à créer une structure pour le triangle.

typedef struct position GLKVector2; Triangle;

N'oubliez pas d'ajouter une déclaration d'importation pour le GLKMath bibliothèque au sommet de ViewController.m.

#importation 

Pour rendre le triangle, vous devez créer un MTLRenderPipelineDescriptor objet et un MTLRenderPipelineState objet. En outre, chaque objet dessiné sur l'écran appartient à la MTLBuffer classe.

MTLRenderPipelineDescriptor * renderPipelineDescriptor; identifiant  renderPipelineState; identifiant  objet;

Avec ces variables d’instance déclarées, vous devez maintenant les initialiser dans le viewDidLoad méthode comme je l'ai expliqué plus tôt.

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

Pour ombrer le triangle, nous aurons besoin de shaders en métal. Les shaders métalliques doivent être affectés à la MTLRenderPipelineDescriptor objet et encapsulé à travers un MTLLibrary protocole. Cela peut sembler complexe, mais vous devez uniquement utiliser les lignes de code suivantes:

identifiant  lib = [mtlDevice newDefaultLibrary]; renderPipelineDescriptor.vertexFunction = [lib newFunctionWithName: @ "VertexColor"]; renderPipelineDescriptor.fragmentFunction = [lib newFunctionWithName: @ "FragmentColor"]; renderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor: erreur renderPipelineDescriptor: nil];

La première ligne crée un objet conforme à la MTLLibrary protocole. Dans la deuxième ligne, nous indiquons à la bibliothèque quelle méthode doit être invoquée dans le shader pour exécuter le passage de sommet dans le pipeline de rendu. Dans la troisième ligne, nous répétons cette étape au niveau des pixels, les fragments. Enfin, à la dernière ligne, nous créons un MTLRenderPipelineState objet.

Dans Metal, vous pouvez définir les coordonnées du système, mais dans ce tutoriel, vous utiliserez le système de coordonnées par défaut, c'est-à-dire que les coordonnées du centre de l'écran sont (0,0).

Dans le bloc de code suivant, nous créons un objet triangle avec trois coordonnées, (-5f, 0.0f), (0.5f, 0.0f), (0.0f, 0.5f).

Triangle triangle [3] = -.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f;

Nous ajoutons ensuite le triangle au objet, qui crée un tampon pour le triangle.

objet = [mtlDevice newBufferWithBytes: & triangle length: sizeof (Triangle [3]) options: MTLResourceOptionCPUCacheModeDefault];

C'est ce que l'achèvement viewDidLoad la méthode devrait ressembler à.

- (void) viewDidLoad [super viewDidLoad]; mtlDevice = MTLCreateSystemDefaultDevice (); mtlCommandQueue = [mtlDevice newCommandQueue]; metalLayer = [couche CAMetalLayer]; [metalLayer setDevice: mtlDevice]; [metalLayer setPixelFormat: MTLPixelFormatBGRA8Unorm]; metalLayer.framebufferOnly = YES; [metalLayer setFrame: self.view.layer.frame]; [self.view.layer addSublayer: metalLayer]; [auto.view setOpaque: YES]; [self.view setBackgroundColor: nil]; [self.view setContentScaleFactor: [UIScreen mainScreen] .scale]; // Créer un pipeline réutilisable renderPipelineDescriptor = [MTLRenderPipelineDescriptor new]; renderPipelineDescriptor.colorAttachments [0] .pixelFormat = MTLPixelFormatBGRA8Unorm; identifiant  lib = [mtlDevice newDefaultLibrary]; renderPipelineDescriptor.vertexFunction = [lib newFunctionWithName: @ "VertexColor"]; renderPipelineDescriptor.fragmentFunction = [lib newFunctionWithName: @ "FragmentColor"]; renderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor: erreur renderPipelineDescriptor: nil]; Triangle triangle [3] = -.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f; objet = [mtlDevice newBufferWithBytes: & triangle length: sizeof (Triangle [3]) options: MTLResourceOptionCPUCacheModeDefault]; displayLink = [CADisplayLink displayLinkWithTarget: sélecteur automatique: @selector (renderScene)]; [displayLink addToRunLoop: [NSRunLoop currentRunLoop] pourMode: NSDefaultRunLoopMode]; 

le viewDidLoad la méthode est terminée, mais il manque une dernière étape, la création des shaders.

8. Créer des shaders

Pour créer un shader en métal, sélectionnez Nouveau> Fichier…  du Fichier menu, choisissez La source > Lime en métal du iOS section, et nommez-le MyShader. Xcode créera alors un nouveau fichier pour vous, MyShader.metal.

En haut, vous devriez voir les deux lignes de code suivantes. Le premier comprend le Bibliothèque standard en métal tandis que le second utilise le métal espace de noms.

#comprendre  utiliser le métal de l'espace de noms;

La première étape consiste à copier la structure en triangle dans le shader. Les shaders sont généralement divisés en deux opérations différentes, le sommet et le pixel (fragments). Le premier est lié à la position du sommet tandis que le second est lié à la couleur finale de ce sommet et à toutes les positions des pixels à l'intérieur du polygone. Vous pouvez le voir de cette façon, le premier pixellisera le polygone, les pixels du polygone, et le second ombrera ces mêmes pixels..

Comme ils ont besoin de communiquer de manière unidirectionnelle, d'un sommet à un fragment, il est préférable de créer une structure pour les données qui seront transmises. Dans ce cas, nous passons seulement la position.

typedef struct float4 position [[position]];  TriangleOutput;

Créons maintenant les méthodes vertex et fragment. Rappelez-vous quand vous avez programmé le RenderPipelineDescriptor objet pour le sommet et le fragment? Vous avez utilisé le newFunctionWithName méthode, en passant dans un NSString objet. Cette chaîne est le nom de la méthode que vous appelez dans le shader. Cela signifie que vous devez déclarer deux méthodes avec ces noms., VertexColor et FragmentColor.

Qu'est-ce que ça veut dire? Vous pouvez créer vos shaders et les nommer comme vous le souhaitez, mais vous devez appeler les méthodes exactement comme vous les déclarez et elles doivent avoir des noms uniques..

Dans vos shaders, ajoutez le bloc de code suivant.

sommet TriangleOutput VertexColor (dispositif const Triangle * sommets [[tampon (0)]], index de constante [[id_ vertex]]) TriangleOutput out; out.position = float4 (Vertices [index] .position, 0.0, 1.0); retourner  fragment half4 FragmentColor (vide) return half4 (1.0, 0.0, 0.0, 1.0); 

le VertexColor méthode recevra les données stockées en position 0 de la mémoire tampon (alloué en mémoire) et la vertex_id du sommet. Depuis que nous avons déclaré un triangle à trois sommets, le vertex_id sera 0, 1, et 2. Il produit un TriangleOutput objet qui est automatiquement reçu par le FragmentColor. Enfin, chaque pixel à l’intérieur de ces trois sommets sera ombré en rouge..

C'est tout. Construisez et exécutez votre application et profitez de votre première nouvelle application Metal 60 fps.

9. Ressources externes

Si vous souhaitez en savoir plus sur le framework Metal et son fonctionnement, vous pouvez consulter plusieurs autres ressources:

  • WWDC 2014 (Travailler avec des sections métalliques)
  • Cadre métallique de référence
  • Guide de programmation en métal

Conclusion

Ceci conclut notre tutoriel d’introduction au nouveau framework Metal. Si vous avez des questions ou des commentaires, n'hésitez pas à laisser une ligne dans les commentaires.