Difference between revisions of "BGRABitmap tutorial 8/fr"

From Lazarus wiki
Jump to navigationJump to search
m (Text replace - "delphi>" to "syntaxhighlight>")
Line 14: Line 14:
  
 
Avec l'inspecteur d'objet, ajouter un gestionnaire OnPaint et écrivez :
 
Avec l'inspecteur d'objet, ajouter un gestionnaire OnPaint et écrivez :
<delphi>procedure TForm1.FormPaint(Sender: TObject);
+
<syntaxhighlight>procedure TForm1.FormPaint(Sender: TObject);
 
var
 
var
 
   image,tex: TBGRABitmap;
 
   image,tex: TBGRABitmap;
Line 40: Line 40:
 
     image.Draw(Canvas,0,0,True);
 
     image.Draw(Canvas,0,0,True);
 
     image.free;   
 
     image.free;   
end;</delphi>
+
end;</syntaxhighlight>
  
 
Comme vous pouvez le voir, une texture est juste une image. Pour remplir une ellipse avec une texture, passez juste la texture en paramètre à la place de la couleur.
 
Comme vous pouvez le voir, une texture est juste une image. Pour remplir une ellipse avec une texture, passez juste la texture en paramètre à la place de la couleur.
Line 49: Line 49:
  
 
Ajoutez les lignes suivantes avant tex.Free :
 
Ajoutez les lignes suivantes avant tex.Free :
<delphi>    image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,c,11);
+
<syntaxhighlight>    image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,c,11);
     image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,tex,9); </delphi>
+
     image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,tex,9); </syntaxhighlight>
  
 
La première commande dessine un rectangle arrondi large (un pinceau de largeur 11) qui inclut le bord. La seconde commande remplit la texture avec une largeur plus petite (9). Cela fonctionne parfaitement tant que la texture n'est pas transparente.
 
La première commande dessine un rectangle arrondi large (un pinceau de largeur 11) qui inclut le bord. La seconde commande remplit la texture avec une largeur plus petite (9). Cela fonctionne parfaitement tant que la texture n'est pas transparente.
Line 67: Line 67:
  
 
Avec l'inspecteur d'objet, définissez un gestionnaire OnPaint avec :
 
Avec l'inspecteur d'objet, définissez un gestionnaire OnPaint avec :
<delphi>procedure TForm1.FormPaint(Sender: TObject);
+
<syntaxhighlight>procedure TForm1.FormPaint(Sender: TObject);
 
var
 
var
 
   image,tex: TBGRABitmap;
 
   image,tex: TBGRABitmap;
Line 80: Line 80:
 
     image.Draw(Canvas,0,0,True);
 
     image.Draw(Canvas,0,0,True);
 
     image.free;   
 
     image.free;   
end;</delphi>
+
end;</syntaxhighlight>
  
 
Ce code crée une texture de 100x100, et remplit la fenêtre avec. Vous devriez obtenir quelque chose comme cela :
 
Ce code crée une texture de 100x100, et remplit la fenêtre avec. Vous devriez obtenir quelque chose comme cela :
Line 89: Line 89:
  
 
C'est très noir et blanc. Vous pouvez ajouter quelques couleurs. Pour cela, nous avons d'une fonction pour interpoler les valeurs. En voici une :
 
C'est très noir et blanc. Vous pouvez ajouter quelques couleurs. Pour cela, nous avons d'une fonction pour interpoler les valeurs. En voici une :
<delphi>  function Interp256(value1,value2,position: integer): integer; inline;
+
<syntaxhighlight>  function Interp256(value1,value2,position: integer): integer; inline;
 
   begin
 
   begin
 
       result := (value1*(256-position) + value2*position) shr 8;
 
       result := (value1*(256-position) + value2*position) shr 8;
   end;</delphi>
+
   end;</syntaxhighlight>
 
Cette fonction calcule une valeur allant de value1 à value2. Position est un nombre entre 0 et 256 indiquant si on se rapproche de la deuxième valeur. L'expression "shr 8" est un équivalent optimisé de "div 256" pour des valeurs positives. C'est un décalage binaires de 8 chiffres.
 
Cette fonction calcule une valeur allant de value1 à value2. Position est un nombre entre 0 et 256 indiquant si on se rapproche de la deuxième valeur. L'expression "shr 8" est un équivalent optimisé de "div 256" pour des valeurs positives. C'est un décalage binaires de 8 chiffres.
  
 
Nous voulons interpoler des couleurs, alors écrivons une fonction pour cela :
 
Nous voulons interpoler des couleurs, alors écrivons une fonction pour cela :
<delphi>  function Interp256(color1,color2: TBGRAPixel; position: integer): TBGRAPixel; inline;
+
<syntaxhighlight>  function Interp256(color1,color2: TBGRAPixel; position: integer): TBGRAPixel; inline;
 
   begin
 
   begin
 
       result.red := Interp256(color1.red,color2.red, position);
 
       result.red := Interp256(color1.red,color2.red, position);
Line 102: Line 102:
 
       result.blue := Interp256(color1.blue,color2.blue, position);
 
       result.blue := Interp256(color1.blue,color2.blue, position);
 
       result.alpha := Interp256(color1.alpha,color2.alpha, position);
 
       result.alpha := Interp256(color1.alpha,color2.alpha, position);
   end;</delphi>
+
   end;</syntaxhighlight>
 
C'est assez évident : chaque composante est interpolée entre la valeur pour color1 et pour color2.
 
C'est assez évident : chaque composante est interpolée entre la valeur pour color1 et pour color2.
  
 
Maintenant, nous avons tout le nécessaire pour faire de la couleur. Après CreatePerlinNoiseMap, ajoutez les lignes suivantes :
 
Maintenant, nous avons tout le nécessaire pour faire de la couleur. Après CreatePerlinNoiseMap, ajoutez les lignes suivantes :
<delphi>    p := tex.Data;
+
<syntaxhighlight>    p := tex.Data;
 
     for i := 0 to tex.NbPixels-1 do
 
     for i := 0 to tex.NbPixels-1 do
 
     begin
 
     begin
 
       p^ := Interp256( BGRA(0,128,0), BGRA(192,255,0), p^.red );
 
       p^ := Interp256( BGRA(0,128,0), BGRA(192,255,0), p^.red );
 
       inc(p);
 
       inc(p);
     end;  </delphi>
+
     end;  </syntaxhighlight>
 
Vous aurez besoin des variables 'p' et 'i', alors cliquez sur chacune et pressez Ctrl-Shift-C.
 
Vous aurez besoin des variables 'p' et 'i', alors cliquez sur chacune et pressez Ctrl-Shift-C.
  
Line 123: Line 123:
  
 
Au lieu de varier continuellement, la couleur peut être changée avec un seuil. Par exemple, nous pouvons délimiter la mer et des îles :
 
Au lieu de varier continuellement, la couleur peut être changée avec un seuil. Par exemple, nous pouvons délimiter la mer et des îles :
<delphi>    p := tex.Data;
+
<syntaxhighlight>    p := tex.Data;
 
     for i := 0 to tex.NbPixels-1 do
 
     for i := 0 to tex.NbPixels-1 do
 
     begin
 
     begin
Line 130: Line 130:
 
         p^ := BGRA(0,128,196); //île
 
         p^ := BGRA(0,128,196); //île
 
       inc(p);
 
       inc(p);
     end;  </delphi>
+
     end;  </syntaxhighlight>
  
 
Nous pouvons utiliser davantage de seuils. Voilà par exemple un camouflage militaire :
 
Nous pouvons utiliser davantage de seuils. Voilà par exemple un camouflage militaire :
<delphi>    p := result.Data;
+
<syntaxhighlight>    p := result.Data;
 
     for i := 0 to result.NbPixels-1 do
 
     for i := 0 to result.NbPixels-1 do
 
     begin
 
     begin
Line 142: Line 142:
 
         p^:= BGRA(161,157,121);
 
         p^:= BGRA(161,157,121);
 
       inc(p);
 
       inc(p);
     end;  </delphi>
+
     end;  </syntaxhighlight>
  
 
[[Image:BGRATutorial8d.png]]
 
[[Image:BGRATutorial8d.png]]
Line 150: Line 150:
 
Nous pouvons appliquer la fonction sinus au valeurs du bruit. Créons pour cela une procédure :
 
Nous pouvons appliquer la fonction sinus au valeurs du bruit. Créons pour cela une procédure :
  
<delphi>
+
<syntaxhighlight>
 
   function CreateCustomTexture(tx,ty: integer): TBGRABitmap;
 
   function CreateCustomTexture(tx,ty: integer): TBGRABitmap;
 
   var
 
   var
Line 166: Line 166:
 
     end;
 
     end;
 
   end;
 
   end;
</delphi>
+
</syntaxhighlight>
 
L'oscillation de couleur est une valeur entre 0 et 256. Elle est calculée à partir de l'intensité (p^.red). On y applique la fonction sinus avec une demi-période de 32. Cela donne un nombre entre -1 et 1. Pour le ramener dans l'intervalle 0..1, nous ajouter 1 et divisons par 2. Enfin, nous multiplions par 256 pour avoir un entier pour Interp256.
 
L'oscillation de couleur est une valeur entre 0 et 256. Elle est calculée à partir de l'intensité (p^.red). On y applique la fonction sinus avec une demi-période de 32. Cela donne un nombre entre -1 et 1. Pour le ramener dans l'intervalle 0..1, nous ajouter 1 et divisons par 2. Enfin, nous multiplions par 256 pour avoir un entier pour Interp256.
  
 
La procédure OnPaint devient plus simple :
 
La procédure OnPaint devient plus simple :
<delphi>
+
<syntaxhighlight>
 
var
 
var
 
   image,tex: TBGRABitmap;
 
   image,tex: TBGRABitmap;
Line 185: Line 185:
 
     image.free;
 
     image.free;
 
end;  
 
end;  
</delphi>
+
</syntaxhighlight>
  
 
Vous devriez obtenir une image ressemblant à cela :
 
Vous devriez obtenir une image ressemblant à cela :
Line 192: Line 192:
  
 
Maintenant, si on veut que cela ressemble à du marbre, nous avons besoin de moins d'oscillation. Par exemple, nous pouvons utiliser une demi-période de 80. Sur le marbre, les parties sombres sont très fines. Nous pouvons déformer les oscillations en appliquant une fonction 'puissance' : un exposant entre 0 et 1 rendra la valeur plus proche de 1 et un exposant plus grand que 1 rendra la valeur plus proche de 0. Changeons donc l'oscillation dans CreateCustomTexture :
 
Maintenant, si on veut que cela ressemble à du marbre, nous avons besoin de moins d'oscillation. Par exemple, nous pouvons utiliser une demi-période de 80. Sur le marbre, les parties sombres sont très fines. Nous pouvons déformer les oscillations en appliquant une fonction 'puissance' : un exposant entre 0 et 1 rendra la valeur plus proche de 1 et un exposant plus grand que 1 rendra la valeur plus proche de 0. Changeons donc l'oscillation dans CreateCustomTexture :
<delphi>    colorOscillation := round(power((sin(p^.red*Pi/80)+1)/2,0.2)*256); </delphi>
+
<syntaxhighlight>    colorOscillation := round(power((sin(p^.red*Pi/80)+1)/2,0.2)*256); </syntaxhighlight>
  
 
Nous avons alors quelque chose qui ressemble beaucoup plus à du marbre :
 
Nous avons alors quelque chose qui ressemble beaucoup plus à du marbre :
Line 201: Line 201:
  
 
Une texture de bois peut être réalisée avec des fonctions sinus également. La texture de bois contient 2 oscillations, une avec des couleur claires, et une autre avec des couleurs foncées. Alors nous devons appliquer une variation globale entre ces oscillations :
 
Une texture de bois peut être réalisée avec des fonctions sinus également. La texture de bois contient 2 oscillations, une avec des couleur claires, et une autre avec des couleurs foncées. Alors nous devons appliquer une variation globale entre ces oscillations :
<delphi>  function CreateWoodTexture(tx,ty: integer): TBGRABitmap;
+
<syntaxhighlight>  function CreateWoodTexture(tx,ty: integer): TBGRABitmap;
 
   var
 
   var
 
     colorOscillation, globalColorVariation: integer;
 
     colorOscillation, globalColorVariation: integer;
Line 217: Line 217:
 
       inc(p);
 
       inc(p);
 
     end;
 
     end;
   end;</delphi>
+
   end;</syntaxhighlight>
  
 
Ici, la demi-période est 16 et la variation globale est simplement l'intensité. Le résultat ressemble à cela :
 
Ici, la demi-période est 16 et la variation globale est simplement l'intensité. Le résultat ressemble à cela :
Line 224: Line 224:
  
 
La plupart du temps, une texture de bois est orientée selon un axe. Pour faire cela, à la place d'utiliser l'intensité seulement comme position globale, nous avons besoin de la combiner avec la position x :
 
La plupart du temps, une texture de bois est orientée selon un axe. Pour faire cela, à la place d'utiliser l'intensité seulement comme position globale, nous avons besoin de la combiner avec la position x :
<delphi>  function CreateVerticalWoodTexture(tx,ty: integer): TBGRABitmap;
+
<syntaxhighlight>  function CreateVerticalWoodTexture(tx,ty: integer): TBGRABitmap;
 
   var
 
   var
 
     globalPos: single;
 
     globalPos: single;
Line 246: Line 246:
 
       if x = tx then x := 0;
 
       if x = tx then x := 0;
 
     end;
 
     end;
   end; </delphi>
+
   end; </syntaxhighlight>
  
 
Nous obtenons cela :
 
Nous obtenons cela :

Revision as of 13:55, 24 March 2012

Deutsch (de) English (en) español (es) français (fr)


Accueil | Tutoriel 1 | Tutoriel 2 | Tutoriel 3 | Tutoriel 4 | Tutoriel 5 | Tutoriel 6 | Tutoriel 7 | Tutoriel 8 | Tutoriel 9 | Tutoriel 10 | Tutoriel 11 | Tutoriel 12 | Edit

Ce tutoriel montre comment utiliser les textures.

Création d'un nouveau projet

Créez un nouveau projet et ajouter la référence à BGRABitmap, de la même façon que dans le premier tutoriel.

Utilisation des textures de pinceau

La texture la plus simple est hachurée.

Avec l'inspecteur d'objet, ajouter un gestionnaire OnPaint et écrivez :

procedure TForm1.FormPaint(Sender: TObject);
var
  image,tex: TBGRABitmap;
  c: TBGRAPixel;
  x,y,rx,ry: single;

begin
    image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
    c := ColorToBGRA(ColorToRGB(clWindowText));

    //coordonnées de l'ellipse
    x := 150;
    y := 100;
    rx := 100;
    ry := 50;

    //charge un pinceau "diagcross" avec un motif blanc sur fond orange
    tex := image.CreateBrushTexture(bsDiagCross,BGRAWhite,BGRA(255,192,0)) as TBGRABitmap;

    image.FillEllipseAntialias(x,y,rx-0.5,ry-0.5,tex);
    image.EllipseAntialias(x,y,rx,ry,c,1); //draw outline

    tex.Free;

    image.Draw(Canvas,0,0,True);
    image.free;  
end;

Comme vous pouvez le voir, une texture est juste une image. Pour remplir une ellipse avec une texture, passez juste la texture en paramètre à la place de la couleur.

Deux commandes définissent l'ellipse. La première est le remplissage, la seconde est le contour. Notez que le rayon est 0,5 pixel plus petit pour le remplissage. En effet, quand la taille du pinceau est 1, le rayon interieur est 0,5 plus petit et le rayon extérieur 0,5 pixel plus grand.

En utilisant la commande pour le contour, nous dessinons une ellipse avec texture et un bord. Mais si la fonction de contour n'est pas disponible, vous pouvez aussi utiliser une autre commande de remplissage avec un plus grand rayon et la couleur du bord, puis un rayon plus petit pour l'intérieur.

Ajoutez les lignes suivantes avant tex.Free :

    image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,c,11);
    image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,tex,9);

La première commande dessine un rectangle arrondi large (un pinceau de largeur 11) qui inclut le bord. La seconde commande remplit la texture avec une largeur plus petite (9). Cela fonctionne parfaitement tant que la texture n'est pas transparente.

Exécution du programme

Vous devriez obtenir un rectangle arrondi avec une ellipse à l'intérieur. Chaque forme est remplie avec une texture orange.

BGRATutorial8.png

Génération de textures

Bruit de Perlin simple

Il est possible de générer des textures aléatoires répétables en utilisant CreateCyclicPerlinNoiseMap, qui peut être trouvé dans l'unité BGRAGradient.

Avec l'inspecteur d'objet, définissez un gestionnaire OnPaint avec :

procedure TForm1.FormPaint(Sender: TObject);
var
  image,tex: TBGRABitmap;

begin
    image := TBGRABitmap.Create(ClientWidth,ClientHeight);

    tex := CreateCyclicPerlinNoiseMap(100,100);
    image.FillRect(0,0,image.Width,image.Height, tex);
    tex.free;

    image.Draw(Canvas,0,0,True);
    image.free;  
end;

Ce code crée une texture de 100x100, et remplit la fenêtre avec. Vous devriez obtenir quelque chose comme cela :

BGRATutorial8b.png

Changer la couleur

C'est très noir et blanc. Vous pouvez ajouter quelques couleurs. Pour cela, nous avons d'une fonction pour interpoler les valeurs. En voici une :

  function Interp256(value1,value2,position: integer): integer; inline;
  begin
       result := (value1*(256-position) + value2*position) shr 8;
  end;

Cette fonction calcule une valeur allant de value1 à value2. Position est un nombre entre 0 et 256 indiquant si on se rapproche de la deuxième valeur. L'expression "shr 8" est un équivalent optimisé de "div 256" pour des valeurs positives. C'est un décalage binaires de 8 chiffres.

Nous voulons interpoler des couleurs, alors écrivons une fonction pour cela :

  function Interp256(color1,color2: TBGRAPixel; position: integer): TBGRAPixel; inline;
  begin
       result.red := Interp256(color1.red,color2.red, position);
       result.green := Interp256(color1.green,color2.green, position);
       result.blue := Interp256(color1.blue,color2.blue, position);
       result.alpha := Interp256(color1.alpha,color2.alpha, position);
  end;

C'est assez évident : chaque composante est interpolée entre la valeur pour color1 et pour color2.

Maintenant, nous avons tout le nécessaire pour faire de la couleur. Après CreatePerlinNoiseMap, ajoutez les lignes suivantes :

    p := tex.Data;
    for i := 0 to tex.NbPixels-1 do
    begin
      p^ := Interp256( BGRA(0,128,0), BGRA(192,255,0), p^.red );
      inc(p);
    end;

Vous aurez besoin des variables 'p' et 'i', alors cliquez sur chacune et pressez Ctrl-Shift-C.

Cette boucle prend chaque pixel et crée une couleur de vert foncé jusqu'à jaune-vert.

Nous obtenons une couleur vert-arbre :

BGRATutorial8c.png

Utilisation de seuils

Au lieu de varier continuellement, la couleur peut être changée avec un seuil. Par exemple, nous pouvons délimiter la mer et des îles :

    p := tex.Data;
    for i := 0 to tex.NbPixels-1 do
    begin
      if p^.red > 196 then
        p^ := BGRA(192,160,96) else //mer
        p^ := BGRA(0,128,196); //île
      inc(p);
    end;

Nous pouvons utiliser davantage de seuils. Voilà par exemple un camouflage militaire :

    p := result.Data;
    for i := 0 to result.NbPixels-1 do
    begin
      v := p^.red;
      if v < 64 then p^:= BGRA(31,33,46) else
      if v < 128 then p^:= BGRA(89,71,57) else
      if v < 192 then p^:= BGRA(80,106,67) else
        p^:= BGRA(161,157,121);
      inc(p);
    end;

BGRATutorial8d.png

Fonction sinus

Nous pouvons appliquer la fonction sinus au valeurs du bruit. Créons pour cela une procédure :

  function CreateCustomTexture(tx,ty: integer): TBGRABitmap;
  var
    colorOscillation: integer;
    p: PBGRAPixel;
    i: Integer;
  begin
    result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1);
    p := result.Data;
    for i := 0 to result.NbPixels-1 do
    begin
      colorOscillation := round(((sin(p^.red*Pi/32)+1)/2)*256);
      p^ := Interp256(BGRA(181,157,105),BGRA(228,227,180),colorOscillation);
      inc(p);
    end;
  end;

L'oscillation de couleur est une valeur entre 0 et 256. Elle est calculée à partir de l'intensité (p^.red). On y applique la fonction sinus avec une demi-période de 32. Cela donne un nombre entre -1 et 1. Pour le ramener dans l'intervalle 0..1, nous ajouter 1 et divisons par 2. Enfin, nous multiplions par 256 pour avoir un entier pour Interp256.

La procédure OnPaint devient plus simple :

var
  image,tex: TBGRABitmap;

begin
    image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));

    tex := CreateCustomTexture(100,100);
    image.FillRoundRectAntialias(20,20,300,200,20,20,tex);
    image.RoundRectAntialias(20,20,300,200,20,20,BGRABlack,1);
    tex.free;

    image.Draw(Canvas,0,0,True);
    image.free;
end;

Vous devriez obtenir une image ressemblant à cela :

BGRATutorial8e.png

Maintenant, si on veut que cela ressemble à du marbre, nous avons besoin de moins d'oscillation. Par exemple, nous pouvons utiliser une demi-période de 80. Sur le marbre, les parties sombres sont très fines. Nous pouvons déformer les oscillations en appliquant une fonction 'puissance' : un exposant entre 0 et 1 rendra la valeur plus proche de 1 et un exposant plus grand que 1 rendra la valeur plus proche de 0. Changeons donc l'oscillation dans CreateCustomTexture :

    colorOscillation := round(power((sin(p^.red*Pi/80)+1)/2,0.2)*256);

Nous avons alors quelque chose qui ressemble beaucoup plus à du marbre :

BGRATutorial8f.png

Texture de bois

Une texture de bois peut être réalisée avec des fonctions sinus également. La texture de bois contient 2 oscillations, une avec des couleur claires, et une autre avec des couleurs foncées. Alors nous devons appliquer une variation globale entre ces oscillations :

  function CreateWoodTexture(tx,ty: integer): TBGRABitmap;
  var
    colorOscillation, globalColorVariation: integer;
    p: PBGRAPixel;
    i: Integer;
  begin
    result := CreateCyclicPerlinNoiseMap(tx,ty);
    p := result.Data;
    for i := 0 to result.NbPixels-1 do
    begin
      colorOscillation := round(sqrt((sin(p^.red*Pi/16)+1)/2)*256);
      globalColorVariation := p^.red;
      p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation),
                      Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation);
      inc(p);
    end;
  end;

Ici, la demi-période est 16 et la variation globale est simplement l'intensité. Le résultat ressemble à cela :

BGRATutorial8g.png

La plupart du temps, une texture de bois est orientée selon un axe. Pour faire cela, à la place d'utiliser l'intensité seulement comme position globale, nous avons besoin de la combiner avec la position x :

  function CreateVerticalWoodTexture(tx,ty: integer): TBGRABitmap;
  var
    globalPos: single;
    colorOscillation, globalColorVariation: integer;
    p: PBGRAPixel;
    i: Integer;
    x: integer;
  begin
    result := CreateCyclicPerlinNoiseMap(tx,ty);
    p := result.Data;
    x := 0;
    for i := 0 to result.NbPixels-1 do
    begin
      globalPos := p^.red*Pi/32 + x*2*Pi/tx*8;
      colorOscillation := round(sqrt((sin(globalPos)+1)/2)*256);
      globalColorVariation := round(sin(globalPos/8)*128+128);
      p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation),
                      Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation);
      inc(p);
      inc(x);
      if x = tx then x := 0;
    end;
  end;

Nous obtenons cela :

Tutorial8h.png


Tutoriel précédent (splines) Tutoriel suivant (éclairage phong et textures)