Difference between revisions of "BGRABitmap tutorial 9/fr"

From Free Pascal wiki
Jump to navigationJump to search
(→‎Phong et lumière: ortograf et qq expl)
m (Fixed syntax highlighting; deleted category already in page template)
 
(4 intermediate revisions by 4 users not shown)
Line 7: Line 7:
 
=== Création d'un nouveau projet ===
 
=== 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 [[BGRABitmap tutorial/fr|le premier tutoriel]].
+
Créez un nouveau projet et ajoutez la référence à [[BGRABitmap]], de la même façon que dans [[BGRABitmap tutorial/fr|le premier tutoriel]].
  
 
=== Phong et lumière ===
 
=== Phong et lumière ===
  
Pour utiliser l'éclairage Phong, vous devez initialiser une classe TPhongShading. Elle est située dans l'unité BGRAGradients.
+
Pour utiliser l'éclairage Phong, vous devez initialiser une classe ''TPhongShading''. Elle est située dans l'unité ''BGRAGradients''.
  
Ajoutons la variable dans la définition de la fenêtre :
+
Ajoutez la variable dans la définition de la fenêtre :
<delphi>TForm1 = class(TForm)  
+
<syntaxhighlight lang="pascal">TForm1 = class(TForm)  
 
   ...
 
   ...
   phong: TPhongShading;    </delphi>
+
   phong: TPhongShading;    </syntaxhighlight>
  
Quand la fenêtre est créée, on crée la classe :
+
Quand la fenêtre est créée, créez la classe :
<delphi>procedure TForm1.FormCreate(Sender: TObject);
+
<syntaxhighlight lang="pascal">procedure TForm1.FormCreate(Sender: TObject);
 
begin
 
begin
 
   phong := TPhongShading.Create;
 
   phong := TPhongShading.Create;
Line 27: Line 27:
 
   phong.LightSourceIntensity := 250;
 
   phong.LightSourceIntensity := 250;
 
   phong.LightSourceDistanceTerm := 200;   
 
   phong.LightSourceDistanceTerm := 200;   
end;  </delphi>
+
end;  </syntaxhighlight>
  
L'indice spéculaire indique la concentration de la lumière réfléchie. Le facteur ambiant indique l'éclairage de base. La variable  LightSourceDistanceTerm indique la distance supplémentaire entre la lumière et l'objet.
+
L'indice spéculaire indique la concentration de la lumière réfléchie. Le facteur ambiant indique l'éclairage de base. La variable  ''LightSourceDistanceTerm'' indique la distance supplémentaire entre la lumière et l'objet.
  
 
Quand le fenêtre est détruite :
 
Quand le fenêtre est détruite :
<delphi>procedure TForm1.FormDestroy(Sender: TObject);
+
<syntaxhighlight lang="pascal">procedure TForm1.FormDestroy(Sender: TObject);
 
begin
 
begin
 
   phong.Free;
 
   phong.Free;
end; </delphi>
+
end; </syntaxhighlight>
  
 
Quand l'image est peinte, on ajoute un objet avec éclairage de Phong :
 
Quand l'image est peinte, on ajoute un objet avec éclairage de Phong :
<delphi>var
+
<syntaxhighlight lang="pascal">var
 
   image: TBGRABitmap;
 
   image: TBGRABitmap;
  
Line 48: Line 48:
 
     image.Draw(Canvas,0,0,True);
 
     image.Draw(Canvas,0,0,True);
 
     image.free;
 
     image.free;
end;  </delphi>
+
end;  </syntaxhighlight>
  
Les paramètres de DrawSphere sont l'image de destination, les bornes de l'objet, l'altitude maximum et la couleur. Le diamètre de la sphère est 100 alors l'altitude maximum est un hémisphère de 50.
+
Les paramètres de ''DrawSphere'' sont l'image de destination, les bornes de l'objet, l'altitude maximum et la couleur. Le diamètre de la sphère est 100 alors l'altitude maximum est un hémisphère de 50.
  
 
Finalement, quand la souris est déplacée, ce serait bien que la source de lumière suive :
 
Finalement, quand la souris est déplacée, ce serait bien que la source de lumière suive :
<delphi>procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
+
<syntaxhighlight lang="pascal">procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
 
   Y: Integer);
 
   Y: Integer);
 
begin
 
begin
 
   phong.LightPosition := point(X,Y);
 
   phong.LightPosition := point(X,Y);
 
   FormPaint(Sender);
 
   FormPaint(Sender);
end;  </delphi>
+
end;  </syntaxhighlight>
  
 
=== Exécution du programme ===
 
=== Exécution du programme ===
Line 69: Line 69:
  
 
La procédure suivante crée un carré de chocolat :
 
La procédure suivante crée un carré de chocolat :
<delphi>function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
+
<syntaxhighlight lang="pascal">function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
 
var
 
var
 
   square,map: TBGRABitmap;
 
   square,map: TBGRABitmap;
Line 102: Line 102:
 
   map.Free;
 
   map.Free;
 
   phong.Free;
 
   phong.Free;
end; </delphi>
+
end; </syntaxhighlight>
  
 
Le module d'éclairage de Phong utilise une carte d'altitudes pour calculer les effets de lumière. Ici, la carte contient un carré.
 
Le module d'éclairage de Phong utilise une carte d'altitudes pour calculer les effets de lumière. Ici, la carte contient un carré.
  
Parm les propriétés de l'éclairage, il y a LightSourceDistanceFactor et LightDestFactor. En mettant ces valeurs à zéro, on permet que la texture soit répétable. En effet, quand le facteur de distance est à zéro, la distance entre la lumière et l'objet n'est pas prise en compte, et quand le facteur de destination de la lumière est à zéro, la position de l'objet n'est pas prise en compte pour le calcul de l'angle de la lumière.
+
Parmi les propriétés de l'éclairage figurent ''LightSourceDistanceFactor'' et ''LightDestFactor''. En mettant ces valeurs à zéro, on permet que la texture soit répétable. En effet, quand le facteur de distance est à zéro, la distance entre la lumière et l'objet n'est pas prise en compte, et quand le facteur de destination de la lumière est à zéro, la position de l'objet n'est pas prise en compte pour le calcul de l'angle de la lumière.
  
 
Quand la fenêtre est créée, on crée le morceau de chocolat :
 
Quand la fenêtre est créée, on crée le morceau de chocolat :
<delphi>  chocolate := CreateChocolateTexture(80,80);  </delphi>
+
<syntaxhighlight lang="pascal">  chocolate := CreateChocolateTexture(80,80);  </syntaxhighlight>
  
 
Et quand la fenêtre est détruite :
 
Et quand la fenêtre est détruite :
<delphi>  chocolate.Free; </delphi>
+
<syntaxhighlight lang="pascal">  chocolate.Free; </syntaxhighlight>
  
Avant phong.DrawSphere dans l'événement OnPaint, ajoutez cette ligne :
+
Avant ''phong.DrawSphere'' dans l'événement ''OnPaint'', ajoutez cette ligne :
<delphi>    image.FillRect(0,0,80*7,80*4,chocolate,dmSet);  </delphi>
+
<syntaxhighlight lang="pascal">    image.FillRect(0,0,80*7,80*4,chocolate,dmSet);  </syntaxhighlight>
  
 
=== Code résultant ===
 
=== Code résultant ===
  
<delphi>unit UMain;
+
<syntaxhighlight lang="pascal">unit UMain;
  
 
{$mode objfpc}{$H+}
 
{$mode objfpc}{$H+}
Line 221: Line 221:
 
   {$I UMain.lrs}
 
   {$I UMain.lrs}
  
end.    </delphi>
+
end.    </syntaxhighlight>
  
 
=== Exécution du programme ===
 
=== Exécution du programme ===
Line 231: Line 231:
 
=== Utiliser le bruit de Perlin et l'éclairage de Phong ensemble ===
 
=== Utiliser le bruit de Perlin et l'éclairage de Phong ensemble ===
  
L'idée est de créer une carte avec un bruit de Perlin, et ensuite d'utiliser l'éclairage de phong pour le rendu. Voici comme créer une texture de pierre :
+
L'idée est de créer une carte avec un bruit de Perlin, et ensuite d'utiliser l'éclairage de Phong pour le rendu. Voici comme créer une texture de pierre :
  
<delphi>  function CreateStoneTexture(tx,ty: integer): TBGRABitmap;
+
<syntaxhighlight lang="pascal">  function CreateStoneTexture(tx,ty: integer): TBGRABitmap;
 
   var
 
   var
 
     temp: TBGRABitmap;
 
     temp: TBGRABitmap;
Line 252: Line 252:
 
     phong.Free;
 
     phong.Free;
 
     temp.Free;
 
     temp.Free;
   end;  </delphi>
+
   end;  </syntaxhighlight>
  
D'abord, on crée une carte cyclique. C'est important pour que la texture soit répétable. Mais ensuite, quand on appliquera l'effet Phong, on aura besoin de préciser que l'effet de lumière aussi soit cyclique. Alors, avec GetPart, on extrait la carte générée avec 2 pixels en plus sur chaque bord, ainsi le calcul de lumière sera appliqué convenablement.
+
D'abord, on crée une carte cyclique. C'est important pour que la texture soit répétable. Mais ensuite, quand on appliquera l'effet Phong, on aura besoin de préciser que l'effet de lumière est lui aussi cyclique. Alors, avec ''GetPart'', on extrait la carte générée avec 2 pixels en plus sur chaque bord, ainsi le calcul de lumière sera-t-il appliqué convenablement.
  
L'appel à phong.Draw avec l'offset (-2,-2) dessine la carte à la position correcte, prenant en compte qu'on a ajouté 2 pixels.
+
L'appel à ''phong.Draw'' avec le décalage (-2,-2) dessine la carte à la position correcte, prenant en compte qu'on a ajouté 2 pixels.
  
Maintenant dans l'événement OnPaint :
+
Maintenant dans l'événement ''OnPaint'' :
<delphi>procedure TForm1.FormPaint(Sender: TObject);
+
<syntaxhighlight lang="pascal">procedure TForm1.FormPaint(Sender: TObject);
 
var
 
var
 
   image: TBGRABitmap;
 
   image: TBGRABitmap;
Line 272: Line 272:
 
     image.Draw(Canvas,0,0,True);
 
     image.Draw(Canvas,0,0,True);
 
     image.free;
 
     image.free;
end;</delphi>
+
end;</syntaxhighlight>
  
 
=== Exécution du programme ===
 
=== Exécution du programme ===
  
Vous devriez voir une fenêtre avec un fond de pierre.
+
Vous devriez voir une fenêtre avec un fond de pierre :
  
 
[[Image:BGRATutorial9c.png]]
 
[[Image:BGRATutorial9c.png]]
Line 284: Line 284:
 
C'est presque la même procédure pour générer de l'eau :
 
C'est presque la même procédure pour générer de l'eau :
  
<delphi>function CreateWaterTexture(tx,ty: integer): TBGRABitmap;
+
<syntaxhighlight lang="pascal">function CreateWaterTexture(tx,ty: integer): TBGRABitmap;
 
const blurSize = 5;
 
const blurSize = 5;
 
var
 
var
Line 307: Line 307:
 
   phong.Free;
 
   phong.Free;
 
   temp.Free;
 
   temp.Free;
end; </delphi>
+
end; </syntaxhighlight>
  
 
La principale différence est qu'on applique un flou pour rendre l'eau ronde et qu'on définit une couleur pour la lumière.
 
La principale différence est qu'on applique un flou pour rendre l'eau ronde et qu'on définit une couleur pour la lumière.
Line 315: Line 315:
 
=== Utilisation de seuil pour faire des traces dans la neige ===
 
=== Utilisation de seuil pour faire des traces dans la neige ===
  
Il est possible de ne garder qu'un sous-intervalle des altitudes, pour avoir une texture qui montre des traces de pas dans la neige.<delphi>function CreateSnowPrintTexture(tx,ty: integer): TBGRABitmap;
+
Il est possible de ne garder qu'un sous-intervalle des altitudes, pour avoir une texture qui montre des traces de pas dans la neige.<syntaxhighlight lang="pascal">function CreateSnowPrintTexture(tx,ty: integer): TBGRABitmap;
 
var
 
var
 
   v: integer;
 
   v: integer;
Line 354: Line 354:
 
   phong.Free;
 
   phong.Free;
 
   temp.Free;
 
   temp.Free;
end;  </delphi>
+
end;  </syntaxhighlight>
  
 
On obtient cela :
 
On obtient cela :
Line 360: Line 360:
 
[[Image:BGRATutorial9e.png]]
 
[[Image:BGRATutorial9e.png]]
  
[[BGRABitmap tutorial 8/fr|Tutoriel précédent (textures)]] [[BGRABitmap tutorial 10/fr|Tutoriel suivant (plaquage de textures)]]
+
[[BGRABitmap tutorial 8/fr|Tutoriel précédent (textures)]] | [[BGRABitmap tutorial 10/fr|Tutoriel suivant (plaquage de textures)]]
 +
 
 +
[[Category:Graphics/fr]]

Latest revision as of 07:16, 10 February 2020

Deutsch (de) English (en) français (fr) русский (ru)


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 l'éclairage de Phong avec les textures.

Création d'un nouveau projet

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

Phong et lumière

Pour utiliser l'éclairage Phong, vous devez initialiser une classe TPhongShading. Elle est située dans l'unité BGRAGradients.

Ajoutez la variable dans la définition de la fenêtre :

TForm1 = class(TForm) 
  ...
  phong: TPhongShading;

Quand la fenêtre est créée, créez la classe :

procedure TForm1.FormCreate(Sender: TObject);
begin
  phong := TPhongShading.Create;
  phong.LightPositionZ := 150;
  phong.SpecularIndex := 20;
  phong.AmbientFactor := 0.4;
  phong.LightSourceIntensity := 250;
  phong.LightSourceDistanceTerm := 200;  
end;

L'indice spéculaire indique la concentration de la lumière réfléchie. Le facteur ambiant indique l'éclairage de base. La variable LightSourceDistanceTerm indique la distance supplémentaire entre la lumière et l'objet.

Quand le fenêtre est détruite :

procedure TForm1.FormDestroy(Sender: TObject);
begin
  phong.Free;
end;

Quand l'image est peinte, on ajoute un objet avec éclairage de Phong :

var
  image: TBGRABitmap;

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

    phong.DrawSphere(image,rect(20,20,120,120),50,BGRA(255,0,0));

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

Les paramètres de DrawSphere sont l'image de destination, les bornes de l'objet, l'altitude maximum et la couleur. Le diamètre de la sphère est 100 alors l'altitude maximum est un hémisphère de 50.

Finalement, quand la souris est déplacée, ce serait bien que la source de lumière suive :

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  phong.LightPosition := point(X,Y);
  FormPaint(Sender);
end;

Exécution du programme

Vous pouvez jouer avec la lumière sur la sphère :

BGRATutorial9a.png

Utiliser l'éclairage de Phong pour créer des textures

La procédure suivante crée un carré de chocolat :

function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
var
  square,map: TBGRABitmap;
  phong: TPhongShading;
  margin: integer;
begin
  margin := tx div 20; //espace vide autour du carré
  square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);

  //crée une carte avec le carré au milieu
  map := TBGRABitmap.Create(tx,ty,BGRABlack);
  map.PutImage(margin,margin,square,dmDrawWithTransparency);

  //applique un flou pour le rendre plus arrondi
  BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
  square.free;

  //création de l'image résultante
  result := TBGRABitmap.Create(tx,ty);

  //utilisation de l'éclairage de Phong
  phong := TPhongShading.Create;
  phong.LightSourceDistanceFactor := 0;
  phong.LightDestFactor := 0;
  phong.LightSourceIntensity := 200;
  phong.AmbientFactor := 0.5;
  phong.LightPosition := Point(-50,-100);
  phong.LightPositionZ := 80;

  //dessine une pièce de chocolat avec une altitude max de 20
  phong.Draw(result,map,20,0,0,BGRA(86,41,38));
  map.Free;
  phong.Free;
end;

Le module d'éclairage de Phong utilise une carte d'altitudes pour calculer les effets de lumière. Ici, la carte contient un carré.

Parmi les propriétés de l'éclairage figurent LightSourceDistanceFactor et LightDestFactor. En mettant ces valeurs à zéro, on permet que la texture soit répétable. En effet, quand le facteur de distance est à zéro, la distance entre la lumière et l'objet n'est pas prise en compte, et quand le facteur de destination de la lumière est à zéro, la position de l'objet n'est pas prise en compte pour le calcul de l'angle de la lumière.

Quand la fenêtre est créée, on crée le morceau de chocolat :

  chocolate := CreateChocolateTexture(80,80);

Et quand la fenêtre est détruite :

  chocolate.Free;

Avant phong.DrawSphere dans l'événement OnPaint, ajoutez cette ligne :

    image.FillRect(0,0,80*7,80*4,chocolate,dmSet);

Code résultant

unit UMain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  ExtCtrls, Buttons, BGRABitmap, BGRABitmapTypes, BGRAGradients;

type
  { TForm1 }

  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure FormPaint(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    phong: TPhongShading;
    chocolate: TBGRABitmap;
  end; 

var
  Form1: TForm1; 

implementation

function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
var
  square,map: TBGRABitmap;
  phong: TPhongShading;
  margin: integer;
begin
  margin := tx div 20;
  square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
  map := TBGRABitmap.Create(tx,ty,BGRABlack);
  map.PutImage(margin,margin,square,dmDrawWithTransparency);
  BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
  square.free;

  result := TBGRABitmap.Create(tx,ty);
  phong := TPhongShading.Create;
  phong.LightSourceDistanceFactor := 0;
  phong.LightDestFactor := 0;
  phong.LightSourceIntensity := 200;
  phong.AmbientFactor := 0.5;
  phong.LightPosition := Point(-50,-100);
  phong.LightPositionZ := 80;
  phong.Draw(result,map,20,0,0,BGRA(86,41,38));
  map.Free;
  phong.Free;
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  phong := TPhongShading.Create;
  phong.LightPositionZ := 150;
  phong.SpecularIndex := 20;
  phong.AmbientFactor := 0.4;
  phong.LightSourceIntensity := 250;
  phong.LightSourceDistanceTerm := 200;

  chocolate := CreateChocolateTexture(80,80);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  phong.Free;
  chocolate.Free;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  phong.LightPosition := point(X,Y);
  FormPaint(Sender);
end;


procedure TForm1.FormPaint(Sender: TObject);
var
  image: TBGRABitmap;
begin
    image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));

    image.FillRect(0,0,80*7,80*4,chocolate,dmSet);
    phong.DrawSphere(image,rect(20,20,120,120),50,BGRA(255,0,0));

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

initialization
  {$I UMain.lrs}

end.

Exécution du programme

Vous devriez voir une plaquette de chocolat appétissante avec une grosse cerise :

BGRATutorial9b.png

Utiliser le bruit de Perlin et l'éclairage de Phong ensemble

L'idée est de créer une carte avec un bruit de Perlin, et ensuite d'utiliser l'éclairage de Phong pour le rendu. Voici comme créer une texture de pierre :

  function CreateStoneTexture(tx,ty: integer): TBGRABitmap;
  var
    temp: TBGRABitmap;
    phong: TPhongShading;
  begin
    result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,0.6);
    temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;

    phong := TPhongShading.Create;
    phong.LightSourceDistanceFactor := 0;
    phong.LightDestFactor := 0;
    phong.LightSourceIntensity := 100;
    phong.LightPositionZ := 100;
    phong.NegativeDiffusionFactor := 0.3;
    phong.AmbientFactor := 0.5;
    phong.Draw(result,temp,30,-2,-2,BGRA(170,170,170));

    phong.Free;
    temp.Free;
  end;

D'abord, on crée une carte cyclique. C'est important pour que la texture soit répétable. Mais ensuite, quand on appliquera l'effet Phong, on aura besoin de préciser que l'effet de lumière est lui aussi cyclique. Alors, avec GetPart, on extrait la carte générée avec 2 pixels en plus sur chaque bord, ainsi le calcul de lumière sera-t-il appliqué convenablement.

L'appel à phong.Draw avec le décalage (-2,-2) dessine la carte à la position correcte, prenant en compte qu'on a ajouté 2 pixels.

Maintenant dans l'événement OnPaint :

procedure TForm1.FormPaint(Sender: TObject);
var
  image: TBGRABitmap;
  stone: TBGRABitmap;
begin
    image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));

    stone := CreateStoneTexture(100,100);
    image.FillEllipseAntialias(200,100,150,50,stone);
    stone.free;

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

Exécution du programme

Vous devriez voir une fenêtre avec un fond de pierre :

BGRATutorial9c.png

Faire de l'eau

C'est presque la même procédure pour générer de l'eau :

function CreateWaterTexture(tx,ty: integer): TBGRABitmap;
const blurSize = 5;
var
  temp: TBGRABitmap;
  phong: TPhongShading;
begin
  result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
  temp:= result.GetPart(rect(-blurSize,-blurSize,tx+blurSize,ty+blurSize)) as TBGRABitmap;
  BGRAReplace(temp,temp.FilterBlurRadial(blurSize,rbFast));

  phong := TPhongShading.Create;
  phong.LightSourceDistanceFactor := 0;
  phong.LightDestFactor := 0;
  phong.LightSourceIntensity := 150;
  phong.LightPositionZ := 80;
  phong.LightColor := BGRA(105,233,240);
  phong.NegativeDiffusionFactor := 0.3;
  phong.SpecularIndex := 20;
  phong.AmbientFactor := 0.4;

  phong.Draw(result,temp,20,-blurSize,-blurSize,BGRA(28,139,166));
  phong.Free;
  temp.Free;
end;

La principale différence est qu'on applique un flou pour rendre l'eau ronde et qu'on définit une couleur pour la lumière.

BGRATutorial9d.png

Utilisation de seuil pour faire des traces dans la neige

Il est possible de ne garder qu'un sous-intervalle des altitudes, pour avoir une texture qui montre des traces de pas dans la neige.

function CreateSnowPrintTexture(tx,ty: integer): TBGRABitmap;
var
  v: integer;
  p: PBGRAPixel;
  i: Integer;

  temp: TBGRABitmap;
  phong: TPhongShading;
begin
  //ici la carte aléatoire est créée
  result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);

  //à présent on applique les seuils
  p := result.Data;
  for i := 0 to result.NbPixels-1 do
  begin
    v := p^.red;
    //si la valeur est au-dessus de 80 ou en-dessous de 50, on la divise par 10 pour rendre la carte horizontale
    if v > 80 then v := (v-80) div 10+80;
    if v < 50 then v := 50-(50-v) div 10;
    p^.red := v;
    p^.green := v;
    p^.blue := v;
    inc(p);
  end;

  //pour que l'éclairage de Phong prenne en compte le cycle
  temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
  //on applique un flou radial
  BGRAReplace(temp,temp.FilterBlurRadial(2,rbFast));
  phong := TPhongShading.Create;
  phong.LightSourceDistanceFactor := 0;
  phong.LightDestFactor := 0;
  phong.LightSourceIntensity := 100;
  phong.LightPositionZ := 100;
  phong.NegativeDiffusionFactor := 0.3; //pour avoir des ombres
  phong.Draw(result,temp,30,-2,-2,BGRAWhite);
  phong.Free;
  temp.Free;
end;

On obtient cela :

BGRATutorial9e.png

Tutoriel précédent (textures) | Tutoriel suivant (plaquage de textures)