Difference between revisions of "BGRABitmap tutorial 9/de"

From Free Pascal wiki
Jump to navigationJump to search
m (translating...)
 
m (translated)
Line 9: Line 9:
 
Erzeugen Sie ein neues Projekt und fügen Sie eine Referenz auf [[BGRABitmap/de|BGRABitmap]] hinzu, genau so wie im [[BGRABitmap tutorial/de|ersten Tutorial]].
 
Erzeugen Sie ein neues Projekt und fügen Sie eine Referenz auf [[BGRABitmap/de|BGRABitmap]] hinzu, genau so wie im [[BGRABitmap tutorial/de|ersten Tutorial]].
  
=== Phong-Schattierung und Licht ===
+
=== Phong-Schattierung und Beleuchtung ===
  
 
Um die Phong-Schattierung zu benutzen, müssen Sie eine TPhongShading-Klasse instantiieren. Diese befindet sich in der Unit 'BGRAGradients'.
 
Um die Phong-Schattierung zu benutzen, müssen Sie eine TPhongShading-Klasse instantiieren. Diese befindet sich in der Unit 'BGRAGradients'.
Line 31: Line 31:
 
Der Specularindex zeigt an, wie konzentriert das reflektierte Licht ist.
 
Der Specularindex zeigt an, wie konzentriert das reflektierte Licht ist.
  
When the form is destroyed :
+
Wenn das Formular zerstört wird:
 
<delphi>procedure TForm1.FormDestroy(Sender: TObject);
 
<delphi>procedure TForm1.FormDestroy(Sender: TObject);
 
begin
 
begin
Line 37: Line 37:
 
end; </delphi>
 
end; </delphi>
  
When the form is painted, add some phong shaded object :
+
Wenn das Formular gezeichnet wird, fügen wir ein phong-schattiertes Objekt ein:
 
<delphi>var
 
<delphi>var
 
   image: TBGRABitmap;
 
   image: TBGRABitmap;
Line 50: Line 50:
 
end;  </delphi>
 
end;  </delphi>
  
The parameter of DrawSphere are the destination image, the bounds of the object, the maximum altitude and the color. The diameter of the sphere is 100 so the maximum altitude of a hemisphere is 50.
+
Die Parameter von DrawSphere sind das Zielbild, die Abmessungen des Objektes, die maximale Höhe und die Farbe. Der Durchmesser der Kugelist 100, also ist die maximale Höhe der Halbkugel 50.
  
Finally when the mouse is moved, it would be nice that the light source followed :
+
Zuletzt wäre es nett, wenn die Lichtquelle den Mauszeigerbewegungen folgen würde:
 
<delphi>procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
 
<delphi>procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
 
   Y: Integer);
 
   Y: Integer);
Line 60: Line 60:
 
end;  </delphi>
 
end;  </delphi>
  
=== Run the program ===
+
=== Starten Sie das Programm ===
  
You should be able to play with the light on the sphere :
+
Sie sollten mit dem Licht auf der Kugel spielen können:
  
 
[[Image:BGRATutorial9a.png]]
 
[[Image:BGRATutorial9a.png]]
  
=== Use phong shading to create textures ===
+
=== Verwenden Sie die Phong-Schattierung, um Texturen zu erzeugen ===
  
The following procedure creates a piece of chocolate :
+
Die folgende Prozedur erzeugt ein Stück Schokolade:
 
<delphi>function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
 
<delphi>function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
 
var
 
var
Line 78: Line 78:
 
   square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
 
   square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
  
   //create a map with the square at the middle
+
   //erzeugt eine Bitmap mit einem Quadrat in der Mitte
 
   map := TBGRABitmap.Create(tx,ty,BGRABlack);
 
   map := TBGRABitmap.Create(tx,ty,BGRABlack);
 
   map.PutImage(margin,margin,square,dmDrawWithTransparency);
 
   map.PutImage(margin,margin,square,dmDrawWithTransparency);
  
   //apply blur to make it smoother
+
   //durch Verwischen erscheint es weicher
 
   BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
 
   BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
 
   square.free;
 
   square.free;
  
   //create resulting bitmap
+
   //erzeugt die resultierende Bitmap
 
   result := TBGRABitmap.Create(tx,ty);
 
   result := TBGRABitmap.Create(tx,ty);
  
   //use phong shading
+
   //benutzt die Phong-Schattierung
 
   phong := TPhongShading.Create;
 
   phong := TPhongShading.Create;
 
   phong.LightSourceDistanceFactor := 0;
 
   phong.LightSourceDistanceFactor := 0;
Line 98: Line 98:
 
   phong.LightPositionZ := 80;
 
   phong.LightPositionZ := 80;
  
   //draw the piece of chocolate with max altitude 20
+
   //zeichnet ein Stück Schokolade mit maximaler Höhe 20
 
   phong.Draw(result,map,20,0,0,BGRA(86,41,38));
 
   phong.Draw(result,map,20,0,0,BGRA(86,41,38));
 
   map.Free;
 
   map.Free;
Line 104: Line 104:
 
end; </delphi>
 
end; </delphi>
  
The phong shader uses a map of altitudes to render the light effects. Here, the map contains a square.
+
Der Phong-Shader benutzt eine Höhenkarte zum Darstellen der Lichteffekte. Hier enthält die Karte ein Quadrat.
  
Among properties of the phong shader, there is LightSourceDistanceFactor and LightDestFactor. Setting these values to zero make the result tilable. Indeed, when the distance factor is zero, the distance between the light and the object is not taken into account, and when the light destination factor is zero, the position of the object is not taken into account when computing the angle of the light.
+
Unter den Eigenschaften des Phong-Shaders gibt es 'LightSourceDistanceFactor' und 'LightDestFactor'. Setzt man diese Werte auf 0 wird das Ergebnis anreihbar. Genau genommen: Wenn der DistanceFactor 0 ist, bleibt die Distanz zwischen der Lichtquelle und dem Objekt unberücksichtigt. Und wenn der LightDestinationFactor 0 ist, dann bleibt die Position des Objektes beim Berechnen des Lichteinfallswinkels unberücksichtigt.
  
Now, when the form is created, create the chocolate texture :
+
Wenn jetzt das Formular erzeugt wird, dann erzeugen wir auch die Schokoladentextur:
 
<delphi>  chocolate := CreateChocolateTexture(80,80);  </delphi>
 
<delphi>  chocolate := CreateChocolateTexture(80,80);  </delphi>
  
And when the form is destroyed :
+
Und wenn das Formular zerstört wird:
 
<delphi>  chocolate.Free; </delphi>
 
<delphi>  chocolate.Free; </delphi>
  
Before phong.DrawSphere in the OnPaint event, add this line :
+
Fügen Sie im OnPaint-Ereignis vor 'phong.DrawSphere' folgende Zeile ein:
 
<delphi>    image.FillRect(0,0,80*7,80*4,chocolate,dmSet);  </delphi>
 
<delphi>    image.FillRect(0,0,80*7,80*4,chocolate,dmSet);  </delphi>
  
=== Resulting code ===
+
=== Resultierender Code ===
  
 
<delphi>unit UMain;
 
<delphi>unit UMain;
Line 223: Line 223:
 
end.    </delphi>
 
end.    </delphi>
  
=== Run the program ===
+
=== Starten Sie das Programm ===
  
You should see a nice bar of chocolate with a big cherry :
+
Sie sehen hoffentlich eine leckere Tafel Schokolade mit einer großen Kirsche:
  
 
[[Image:BGRATutorial9b.png]]
 
[[Image:BGRATutorial9b.png]]
  
=== Using Perlin noise and phong shading together ===
+
=== Gemeinsame Nutzung von Perlin noise und Phong-Schattierung ===
  
The idea is to create a map with a Perlin noise, and then use phong shading to render it. Here is how to create a stone texture :
+
Die Idee dahinter ist, eine Höhenkarte mit dem Perlinrauschen zu erzeugen und dann zur Darstellung die Phong-Schattierung anzuwenden. Damit erzeugen wir hier eine Steintextur:
  
 
<delphi>  function CreateStoneTexture(tx,ty: integer): TBGRABitmap;
 
<delphi>  function CreateStoneTexture(tx,ty: integer): TBGRABitmap;
Line 254: Line 254:
 
   end;  </delphi>
 
   end;  </delphi>
  
First, we create a cyclic map. It's important that it be cyclic in order to make a tilable texture. But then, when we will apply phong shading, we need to make the shader aware of the cycle. So, with GetPart, we extract the generated map with 2 more pixels on each border, so the shader can be applied to the map with the cycle.
+
Zuerst erzeugen wir eine zyklische Karte. Zyklisch ist wichtig für eine anreihbare Textur. Aber wenn wir die Phong-Schattierung anwenden wollen, müssen wir dem Shader diesen Zyklus bekanntgeben. Also extrahieren wir mittels Getpart die erzeugte Karte mit 2 zusätzlichen Pixels zu jeder Seite, sodass der Shader zyklisch auf die Karte angewendet werden kann.
  
The call to phong.Draw with offset (-2,-2) renders the map at the correct location, taking into account that we've added two pixels.
+
Der Aufruf von 'phong.Draw' mit einem Offset (-2,-2) stellt die Karte am rechten Ort dar und berücksichtigt auch unsere zwei zusätzlichen Pixel.
  
Now in the OnPaint event :
+
Jetzt lautet das OnPaint-Ereignis:
 
<delphi>procedure TForm1.FormPaint(Sender: TObject);
 
<delphi>procedure TForm1.FormPaint(Sender: TObject);
 
var
 
var
Line 274: Line 274:
 
end;</delphi>
 
end;</delphi>
  
=== Run the program ===
+
=== Starten Sie das Programm ===
  
You should see a form with a stoned background.
+
Sie sehen ein Formular mit einem steinartigen Hintergrund.
  
 
[[Image:BGRATutorial9c.png]]
 
[[Image:BGRATutorial9c.png]]
  
=== Rendering water ===
+
=== Darstellung von Wasser ===
  
It is almost the same procedure to generate water texture :
+
Fast die gleiche Prozedur erzeugt uns eine Wassertextur:
  
 
<delphi>function CreateWaterTexture(tx,ty: integer): TBGRABitmap;
 
<delphi>function CreateWaterTexture(tx,ty: integer): TBGRABitmap;
Line 309: Line 309:
 
end; </delphi>
 
end; </delphi>
  
The main difference is that we apply a blur filter to make it the water smooth and set the light color.
+
Der Hauptunterschied ist, dass wir einen Weichzeichner auf das Wasser anwenden und die Lichtfarbe anders setzen.
  
 
[[Image:BGRATutorial9d.png]]
 
[[Image:BGRATutorial9d.png]]
  
=== Using thresholds to render snow prints ===
+
=== Verwendung von Schwellenwerten liefert Spuren im Schnee ===
  
It is possible to keep only a small subrange of altitudes, to have a texture that shows foot prints in the snow.
+
Wenn wir uns auf auf einen kleinen Bereich von Höhen beschränken, haben wir eine Textur, die Fussabdrücken im Schnee ähnelt.
 
<delphi>function CreateSnowPrintTexture(tx,ty: integer): TBGRABitmap;
 
<delphi>function CreateSnowPrintTexture(tx,ty: integer): TBGRABitmap;
 
var
 
var
Line 325: Line 325:
 
   phong: TPhongShading;
 
   phong: TPhongShading;
 
begin
 
begin
   //here a random map is generated
+
   //hier wird eine Zufallskarte erzeugt
 
   result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
 
   result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
  
   //now we apply thresholds
+
   //jetzt die Schwellenwerte anwenden
 
   p := result.Data;
 
   p := result.Data;
 
   for i := 0 to result.NbPixels-1 do
 
   for i := 0 to result.NbPixels-1 do
 
   begin
 
   begin
 
     v := p^.red;
 
     v := p^.red;
     //if the value is above 80 or under 50, then we divide it by 10 to make it almost horizontal
+
     //wenn der Wert über 80 oder unter 50 ist, dividieren wir durch 10, dadurch wird es fast horizontal
 
     if v > 80 then v := (v-80) div 10+80;
 
     if v > 80 then v := (v-80) div 10+80;
 
     if v < 50 then v := 50-(50-v) div 10;
 
     if v < 50 then v := 50-(50-v) div 10;
Line 342: Line 342:
 
   end;
 
   end;
  
   //to make phong shader aware of the cycle
+
   //wir geben dem Phong-Shader den Zyklus bekannt
 
   temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
 
   temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
 
   //apply a radial blur
 
   //apply a radial blur
Line 351: Line 351:
 
   phong.LightSourceIntensity := 100;
 
   phong.LightSourceIntensity := 100;
 
   phong.LightPositionZ := 100;
 
   phong.LightPositionZ := 100;
   phong.NegativeDiffusionFactor := 0.3; //want shadows
+
   phong.NegativeDiffusionFactor := 0.3; //ergibt Schatten
 
   phong.Draw(result,temp,30,-2,-2,BGRAWhite);
 
   phong.Draw(result,temp,30,-2,-2,BGRAWhite);
 
   phong.Free;
 
   phong.Free;
Line 357: Line 357:
 
end;  </delphi>
 
end;  </delphi>
  
We obtain this :
+
Wir erhalten dies:
  
 
[[Image:BGRATutorial9e.png]]
 
[[Image:BGRATutorial9e.png]]
  
 
[[BGRABitmap tutorial 8/de|Voriges Tutorial (Texturen)]]
 
[[BGRABitmap tutorial 8/de|Voriges Tutorial (Texturen)]]

Revision as of 17:33, 3 April 2011

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


Home | Tutorial 1 | Tutorial 2 | Tutorial 3 | Tutorial 4 | Tutorial 5 | Tutorial 6 | Tutorial 7 | Tutorial 8 | Tutorial 9 | Tutorial 10 | Tutorial 11 | Tutorial 12 | Tutorial 13 | Tutorial 14 | Tutorial 15 | Tutorial 16 | Edit

Dieses Tutorial zeigt, wie Sie mit der Phong-Schattierung Texturen erzeugen können.

Erzeugen Sie ein neues Projekt

Erzeugen Sie ein neues Projekt und fügen Sie eine Referenz auf BGRABitmap hinzu, genau so wie im ersten Tutorial.

Phong-Schattierung und Beleuchtung

Um die Phong-Schattierung zu benutzen, müssen Sie eine TPhongShading-Klasse instantiieren. Diese befindet sich in der Unit 'BGRAGradients'.

Fügen wir eine Variable in der Formulardefinition hinzu: <delphi>TForm1 = class(TForm)

 ...
 phong: TPhongShading;     </delphi>

Wenn das Formular erzeugt wird, erzeugen wir auch die Klasse: <delphi>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; </delphi>

Der Specularindex zeigt an, wie konzentriert das reflektierte Licht ist.

Wenn das Formular zerstört wird: <delphi>procedure TForm1.FormDestroy(Sender: TObject); begin

 phong.Free;

end; </delphi>

Wenn das Formular gezeichnet wird, fügen wir ein phong-schattiertes Objekt ein: <delphi>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; </delphi>

Die Parameter von DrawSphere sind das Zielbild, die Abmessungen des Objektes, die maximale Höhe und die Farbe. Der Durchmesser der Kugelist 100, also ist die maximale Höhe der Halbkugel 50.

Zuletzt wäre es nett, wenn die Lichtquelle den Mauszeigerbewegungen folgen würde: <delphi>procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,

 Y: Integer);

begin

 phong.LightPosition := point(X,Y);
 FormPaint(Sender);

end; </delphi>

Starten Sie das Programm

Sie sollten mit dem Licht auf der Kugel spielen können:

BGRATutorial9a.png

Verwenden Sie die Phong-Schattierung, um Texturen zu erzeugen

Die folgende Prozedur erzeugt ein Stück Schokolade: <delphi>function CreateChocolateTexture(tx,ty: integer): TBGRABitmap; var

 square,map: TBGRABitmap;
 phong: TPhongShading;
 margin: integer;

begin

 margin := tx div 20; //empty space around the square
 square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
 //erzeugt eine Bitmap mit einem Quadrat in der Mitte
 map := TBGRABitmap.Create(tx,ty,BGRABlack);
 map.PutImage(margin,margin,square,dmDrawWithTransparency);
 //durch Verwischen erscheint es weicher
 BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
 square.free;
 //erzeugt die resultierende Bitmap
 result := TBGRABitmap.Create(tx,ty);
 //benutzt die Phong-Schattierung
 phong := TPhongShading.Create;
 phong.LightSourceDistanceFactor := 0;
 phong.LightDestFactor := 0;
 phong.LightSourceIntensity := 200;
 phong.AmbientFactor := 0.5;
 phong.LightPosition := Point(-50,-100);
 phong.LightPositionZ := 80;
 //zeichnet ein Stück Schokolade mit maximaler Höhe 20
 phong.Draw(result,map,20,0,0,BGRA(86,41,38));
 map.Free;
 phong.Free;

end; </delphi>

Der Phong-Shader benutzt eine Höhenkarte zum Darstellen der Lichteffekte. Hier enthält die Karte ein Quadrat.

Unter den Eigenschaften des Phong-Shaders gibt es 'LightSourceDistanceFactor' und 'LightDestFactor'. Setzt man diese Werte auf 0 wird das Ergebnis anreihbar. Genau genommen: Wenn der DistanceFactor 0 ist, bleibt die Distanz zwischen der Lichtquelle und dem Objekt unberücksichtigt. Und wenn der LightDestinationFactor 0 ist, dann bleibt die Position des Objektes beim Berechnen des Lichteinfallswinkels unberücksichtigt.

Wenn jetzt das Formular erzeugt wird, dann erzeugen wir auch die Schokoladentextur: <delphi> chocolate := CreateChocolateTexture(80,80); </delphi>

Und wenn das Formular zerstört wird: <delphi> chocolate.Free; </delphi>

Fügen Sie im OnPaint-Ereignis vor 'phong.DrawSphere' folgende Zeile ein: <delphi> image.FillRect(0,0,80*7,80*4,chocolate,dmSet); </delphi>

Resultierender Code

<delphi>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. </delphi>

Starten Sie das Programm

Sie sehen hoffentlich eine leckere Tafel Schokolade mit einer großen Kirsche:

BGRATutorial9b.png

Gemeinsame Nutzung von Perlin noise und Phong-Schattierung

Die Idee dahinter ist, eine Höhenkarte mit dem Perlinrauschen zu erzeugen und dann zur Darstellung die Phong-Schattierung anzuwenden. Damit erzeugen wir hier eine Steintextur:

<delphi> 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;   </delphi>

Zuerst erzeugen wir eine zyklische Karte. Zyklisch ist wichtig für eine anreihbare Textur. Aber wenn wir die Phong-Schattierung anwenden wollen, müssen wir dem Shader diesen Zyklus bekanntgeben. Also extrahieren wir mittels Getpart die erzeugte Karte mit 2 zusätzlichen Pixels zu jeder Seite, sodass der Shader zyklisch auf die Karte angewendet werden kann.

Der Aufruf von 'phong.Draw' mit einem Offset (-2,-2) stellt die Karte am rechten Ort dar und berücksichtigt auch unsere zwei zusätzlichen Pixel.

Jetzt lautet das OnPaint-Ereignis: <delphi>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;</delphi>

Starten Sie das Programm

Sie sehen ein Formular mit einem steinartigen Hintergrund.

BGRATutorial9c.png

Darstellung von Wasser

Fast die gleiche Prozedur erzeugt uns eine Wassertextur:

<delphi>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; </delphi>

Der Hauptunterschied ist, dass wir einen Weichzeichner auf das Wasser anwenden und die Lichtfarbe anders setzen.

BGRATutorial9d.png

Verwendung von Schwellenwerten liefert Spuren im Schnee

Wenn wir uns auf auf einen kleinen Bereich von Höhen beschränken, haben wir eine Textur, die Fussabdrücken im Schnee ähnelt. <delphi>function CreateSnowPrintTexture(tx,ty: integer): TBGRABitmap; var

 v: integer;
 p: PBGRAPixel;
 i: Integer;
 temp: TBGRABitmap;
 phong: TPhongShading;

begin

 //hier wird eine Zufallskarte erzeugt
 result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
 //jetzt die Schwellenwerte anwenden
 p := result.Data;
 for i := 0 to result.NbPixels-1 do
 begin
   v := p^.red;
   //wenn der Wert über 80 oder unter 50 ist, dividieren wir durch 10, dadurch wird es fast horizontal
   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;
 //wir geben dem Phong-Shader den Zyklus bekannt
 temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
 //apply a radial blur
 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; //ergibt Schatten
 phong.Draw(result,temp,30,-2,-2,BGRAWhite);
 phong.Free;
 temp.Free;

end; </delphi>

Wir erhalten dies:

BGRATutorial9e.png

Voriges Tutorial (Texturen)