Sign in Join
Wiki copytemporary

BGRABitmap tutorial 9: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-This tutorial shows how to use phong shading to make textures.
1+[[BGRABitmap tutorial|**Home**]] | [[BGRABitmap tutorial 1|**Tutorial 1**]] | [[BGRABitmap tutorial 2|**Tutorial 2**]] | [[BGRABitmap tutorial 3|**Tutorial 3**]] | [[BGRABitmap tutorial 4|**Tutorial 4**]] | [[BGRABitmap tutorial 5|**Tutorial 5**]] | [[BGRABitmap tutorial 6|**Tutorial 6**]] | [[BGRABitmap tutorial 7|**Tutorial 7**]] | [[BGRABitmap tutorial 8|**Tutorial 8**]] | **Tutorial 9** | [[BGRABitmap tutorial 10|**Tutorial 10**]] | [[BGRABitmap tutorial 11|**Tutorial 11**]] | [[BGRABitmap tutorial 12|**Tutorial 12**]] | [[BGRABitmap tutorial 13|**Tutorial 13**]] | [[BGRABitmap tutorial 14|**Tutorial 14**]] | [[BGRABitmap tutorial 15|**Tutorial 15**]] | [[BGRABitmap tutorial 16|**Tutorial 16**]] | [[/wiki.freepascal.org/index.php?title=Template:BGRABitmap tutorial index&action=edit|Edit]]
22
3+This tutorial shows how to use phong shading to make textures.
4+
5+## Contents
6+
7+ * 1 Create a new project
8+ * 2 Phong shading and light
9+ * 3 Run the program
10+ * 4 Use phong shading to create textures
11+ * 5 Resulting code
12+ * 6 Run the program
13+ * 7 Using Perlin noise and phong shading together
14+ * 8 Run the program
15+ * 9 Rendering water
16+ * 10 Using thresholds to render snow prints
17+
318### Create a new project
419
5-Create a new project and add a reference to [[BGRABitmap]], the same way as in [[BGRABitmap tutorial 1|the first tutorial]].
20+Create a new project and add a reference to [[BGRABitmap]], the same way as in [[BGRABitmap tutorial 1|the first tutorial]].
621
722### Phong shading and light
823
9-To use phong shading, you need to instanciate a TPhongShading class. It's located in BGRAGradients unit.
10-
11-Let's add a variable in the form definition:
24+To use phong shading, you need to instanciate a TPhongShading class. It's located in BGRAGradients unit.
1225
13-``` pascal
26+Let's add a variable in the form definition:
27+```
1428TForm1 = class(TForm)
15- ...
16- phong: TPhongShading;
29+ ...
30+ phong: TPhongShading;
1731```
1832
19-When the form is created, we can create the class:
20-
21-``` pascal
33+When the form is created, we can create the class:
34+```
2235procedure TForm1.FormCreate(Sender: TObject);
23-begin
24- phong := TPhongShading.Create;
25- phong.LightPositionZ := 150;
26- phong.SpecularIndex := 20;
27- phong.AmbientFactor := 0.4;
28- phong.LightSourceIntensity := 250;
29- phong.LightSourceDistanceTerm := 200;
30-end;
36+ begin
37+ phong := TPhongShading.Create;
38+ phong.LightPositionZ := 150;
39+ phong.SpecularIndex := 20;
40+ phong.AmbientFactor := 0.4;
41+ phong.LightSourceIntensity := 250;
42+ phong.LightSourceDistanceTerm := 200;
43+ end;
3144```
3245
33-The specular index indicates how concentrated the reflected light is.
34-
35-When the form is destroyed:
46+The specular index indicates how concentrated the reflected light is.
3647
37-``` pascal
48+When the form is destroyed:
49+```
3850procedure TForm1.FormDestroy(Sender: TObject);
39-begin
40- phong.Free;
41-end;
51+ begin
52+ phong.Free;
53+ end;
4254```
4355
44-When the form is painted, add some phong shaded object:
45-
46-``` pascal
56+When the form is painted, add some phong shaded object:
57+```
4758procedure TForm1.FormPaint(Sender: TObject);
48-var
49- image: TBGRABitmap;
50-
51-begin
52- image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
53-
54- phong.DrawSphere(image,rect(20,20,120,120),50,BGRA(255,0,0));
55-
56- image.Draw(Canvas,0,0,True);
57- image.free;
58-end;
59+ var
60+ image: TBGRABitmap;
61+
62+ begin
63+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
64+
65+ phong.DrawSphere(image,rect(20,20,120,120),50,BGRA(255,0,0));
66+
67+ image.Draw(Canvas,0,0,True);
68+ image.free;
69+ end;
5970```
6071
61-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.
62-
63-Finally when the mouse is moved, it would be nice that the light source followed:
72+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.
6473
65-``` pascal
74+Finally when the mouse is moved, it would be nice that the light source followed:
75+```
6676procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
67- Y: Integer);
68-begin
69- phong.LightPosition := point(X,Y);
70- FormPaint(Sender);
71-end;
77+ Y: Integer);
78+ begin
79+ phong.LightPosition := point(X,Y);
80+ FormPaint(Sender);
81+ end;
7282```
7383
7484### Run the program
7585
76-You should be able to play with the light on the sphere:
86+You should be able to play with the light on the sphere:
7787
78-<figure>
79-<img src="BGRATutorial9a.png" title="BGRATutorial9a.png" />
80-<figcaption>BGRATutorial9a.png</figcaption>
81-</figure>
88+[![BGRATutorial9a.png](/wiki-images/f/fd/BGRATutorial9a.png)](</File:BGRATutorial9a.png>)
8289
8390### Use phong shading to create textures
8491
85-The following procedure creates a piece of chocolate:
86-
87-``` pascal
92+The following procedure creates a piece of chocolate:
93+```
8894function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
89-var
90- square,map: TBGRABitmap;
91- phong: TPhongShading;
92- margin: integer;
93-begin
94- margin := tx div 20; //empty space around the square
95- square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
96-
97- //create a map with the square at the middle
98- map := TBGRABitmap.Create(tx,ty,BGRABlack);
99- map.PutImage(margin,margin,square,dmDrawWithTransparency);
100-
101- //apply blur to make it smoother
102- BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
103- square.free;
104-
105- //create resulting bitmap
106- result := TBGRABitmap.Create(tx,ty);
107-
108- //use phong shading
109- phong := TPhongShading.Create;
110- phong.LightSourceDistanceFactor := 0;
111- phong.LightDestFactor := 0;
112- phong.LightSourceIntensity := 200;
113- phong.AmbientFactor := 0.5;
114- phong.LightPosition := Point(-50,-100);
115- phong.LightPositionZ := 80;
116-
117- //draw the piece of chocolate with max altitude 20
118- phong.Draw(result,map,20,0,0,BGRA(86,41,38));
119- map.Free;
120- phong.Free;
121-end;
95+ var
96+ square,map: TBGRABitmap;
97+ phong: TPhongShading;
98+ margin: integer;
99+ begin
100+ margin := tx div 20; //empty space around the square
101+ square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
102+
103+ //create a map with the square at the middle
104+ map := TBGRABitmap.Create(tx,ty,BGRABlack);
105+ map.PutImage(margin,margin,square,dmDrawWithTransparency);
106+
107+ //apply blur to make it smoother
108+ BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
109+ square.free;
110+
111+ //create resulting bitmap
112+ result := TBGRABitmap.Create(tx,ty);
113+
114+ //use phong shading
115+ phong := TPhongShading.Create;
116+ phong.LightSourceDistanceFactor := 0;
117+ phong.LightDestFactor := 0;
118+ phong.LightSourceIntensity := 200;
119+ phong.AmbientFactor := 0.5;
120+ phong.LightPosition := Point(-50,-100);
121+ phong.LightPositionZ := 80;
122+
123+ //draw the piece of chocolate with max altitude 20
124+ phong.Draw(result,map,20,0,0,BGRA(86,41,38));
125+ map.Free;
126+ phong.Free;
127+ end;
122128```
123129
124-The phong shader uses a map of altitudes to render the light effects. Here, the map contains a square.
125-
126-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.
130+The phong shader uses a map of altitudes to render the light effects. Here, the map contains a square.
127131
128-Now, when the form is created, create the chocolate texture:
132+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.
129133
130-``` pascal
131- chocolate := CreateChocolateTexture(80,80);
134+Now, when the form is created, create the chocolate texture:
132135```
133-
134-And when the form is destroyed:
135-
136-``` pascal
137- chocolate.Free;
136+chocolate := CreateChocolateTexture(80,80);
138137```
139138
140-Before phong.DrawSphere in the OnPaint event, add this line:
139+And when the form is destroyed:
140+```
141+chocolate.Free;
142+```
141143
142-``` pascal
143- image.FillRect(0,0,80*7,80*4,chocolate,dmSet);
144+Before phong.DrawSphere in the OnPaint event, add this line:
144145```
146+image.FillRect(0,0,80*7,80*4,chocolate,dmSet);
147+```
145148
146149### Resulting code
147-
148-``` pascal
150+```
149151unit UMain;
150-
151-{$mode objfpc}{$H+}
152-
153-interface
154-
155-uses
156- Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
157- ExtCtrls, Buttons, BGRABitmap, BGRABitmapTypes, BGRAGradients;
158-
159-type
160- { TForm1 }
161-
162- TForm1 = class(TForm)
163- Timer1: TTimer;
164- procedure FormCreate(Sender: TObject);
165- procedure FormDestroy(Sender: TObject);
166- procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
167- procedure FormPaint(Sender: TObject);
168- private
169- { private declarations }
170- public
171- { public declarations }
172- phong: TPhongShading;
173- chocolate: TBGRABitmap;
174- end;
175-
176-var
177- Form1: TForm1;
178-
179-implementation
180-
181-function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
182-var
183- square,map: TBGRABitmap;
184- phong: TPhongShading;
185- margin: integer;
186-begin
187- margin := tx div 20;
188- square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
189- map := TBGRABitmap.Create(tx,ty,BGRABlack);
190- map.PutImage(margin,margin,square,dmDrawWithTransparency);
191- BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
192- square.free;
193-
194- result := TBGRABitmap.Create(tx,ty);
195- phong := TPhongShading.Create;
196- phong.LightSourceDistanceFactor := 0;
197- phong.LightDestFactor := 0;
198- phong.LightSourceIntensity := 200;
199- phong.AmbientFactor := 0.5;
200- phong.LightPosition := Point(-50,-100);
201- phong.LightPositionZ := 80;
202- phong.Draw(result,map,20,0,0,BGRA(86,41,38));
203- map.Free;
204- phong.Free;
205-end;
206-
207-{ TForm1 }
208-
209-procedure TForm1.FormCreate(Sender: TObject);
210-begin
211- phong := TPhongShading.Create;
212- phong.LightPositionZ := 150;
213- phong.SpecularIndex := 20;
214- phong.AmbientFactor := 0.4;
215- phong.LightSourceIntensity := 250;
216- phong.LightSourceDistanceTerm := 200;
217-
218- chocolate := CreateChocolateTexture(80,80);
219-end;
220-
221-procedure TForm1.FormDestroy(Sender: TObject);
222-begin
223- phong.Free;
224- chocolate.Free;
225-end;
226-
227-procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
228- Y: Integer);
229-begin
230- phong.LightPosition := point(X,Y);
231- FormPaint(Sender);
232-end;
233-
234-procedure TForm1.FormPaint(Sender: TObject);
235-var
236- image: TBGRABitmap;
237-begin
238- image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
239-
240- image.FillRect(0,0,80*7,80*4,chocolate,dmSet);
241- phong.DrawSphere(image,rect(20,20,120,120),50,BGRA(255,0,0));
242-
243- image.Draw(Canvas,0,0,True);
244- image.free;
245-end;
246-
247-initialization
248- {$I UMain.lrs}
249-
250-end.
152+
153+ {$mode objfpc}{$H+}
154+
155+ interface
156+
157+ uses
158+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
159+ ExtCtrls, Buttons, BGRABitmap, BGRABitmapTypes, BGRAGradients;
160+
161+ type
162+ { TForm1 }
163+
164+ TForm1 = class(TForm)
165+ Timer1: TTimer;
166+ procedure FormCreate(Sender: TObject);
167+ procedure FormDestroy(Sender: TObject);
168+ procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
169+ procedure FormPaint(Sender: TObject);
170+ private
171+ { private declarations }
172+ public
173+ { public declarations }
174+ phong: TPhongShading;
175+ chocolate: TBGRABitmap;
176+ end;
177+
178+ var
179+ Form1: TForm1;
180+
181+ implementation
182+
183+ function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
184+ var
185+ square,map: TBGRABitmap;
186+ phong: TPhongShading;
187+ margin: integer;
188+ begin
189+ margin := tx div 20;
190+ square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
191+ map := TBGRABitmap.Create(tx,ty,BGRABlack);
192+ map.PutImage(margin,margin,square,dmDrawWithTransparency);
193+ BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
194+ square.free;
195+
196+ result := TBGRABitmap.Create(tx,ty);
197+ phong := TPhongShading.Create;
198+ phong.LightSourceDistanceFactor := 0;
199+ phong.LightDestFactor := 0;
200+ phong.LightSourceIntensity := 200;
201+ phong.AmbientFactor := 0.5;
202+ phong.LightPosition := Point(-50,-100);
203+ phong.LightPositionZ := 80;
204+ phong.Draw(result,map,20,0,0,BGRA(86,41,38));
205+ map.Free;
206+ phong.Free;
207+ end;
208+
209+ { TForm1 }
210+
211+ procedure TForm1.FormCreate(Sender: TObject);
212+ begin
213+ phong := TPhongShading.Create;
214+ phong.LightPositionZ := 150;
215+ phong.SpecularIndex := 20;
216+ phong.AmbientFactor := 0.4;
217+ phong.LightSourceIntensity := 250;
218+ phong.LightSourceDistanceTerm := 200;
219+
220+ chocolate := CreateChocolateTexture(80,80);
221+ end;
222+
223+ procedure TForm1.FormDestroy(Sender: TObject);
224+ begin
225+ phong.Free;
226+ chocolate.Free;
227+ end;
228+
229+ procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
230+ Y: Integer);
231+ begin
232+ phong.LightPosition := point(X,Y);
233+ FormPaint(Sender);
234+ end;
235+
236+
237+ procedure TForm1.FormPaint(Sender: TObject);
238+ var
239+ image: TBGRABitmap;
240+ begin
241+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
242+
243+ image.FillRect(0,0,80*7,80*4,chocolate,dmSet);
244+ phong.DrawSphere(image,rect(20,20,120,120),50,BGRA(255,0,0));
245+
246+ image.Draw(Canvas,0,0,True);
247+ image.free;
248+ end;
249+
250+ initialization
251+ {$I UMain.lrs}
252+
253+ end.
251254```
252255
253256### Run the program
254257
255-You should see a nice bar of chocolate with a big cherry:
258+You should see a nice bar of chocolate with a big cherry:
256259
257-<figure>
258-<img src="BGRATutorial9b.png" title="BGRATutorial9b.png" />
259-<figcaption>BGRATutorial9b.png</figcaption>
260-</figure>
260+[![BGRATutorial9b.png](/wiki-images/6/6f/BGRATutorial9b.png)](</File:BGRATutorial9b.png>)
261261
262262### Using Perlin noise and phong shading together
263263
264-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:
265-
266-``` pascal
267- function CreateStoneTexture(tx,ty: integer): TBGRABitmap;
268- var
269- temp: TBGRABitmap;
270- phong: TPhongShading;
271- begin
272- result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,0.6);
273- temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
274-
275- phong := TPhongShading.Create;
276- phong.LightSourceDistanceFactor := 0;
277- phong.LightDestFactor := 0;
278- phong.LightSourceIntensity := 100;
279- phong.LightPositionZ := 100;
280- phong.NegativeDiffusionFactor := 0.3;
281- phong.AmbientFactor := 0.5;
282- phong.Draw(result,temp,30,-2,-2,BGRA(170,170,170));
283-
284- phong.Free;
285- temp.Free;
286- end;
264+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:
287265```
288-
289-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.
266+function CreateStoneTexture(tx,ty: integer): TBGRABitmap;
267+ var
268+ temp: TBGRABitmap;
269+ phong: TPhongShading;
270+ begin
271+ result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,0.6);
272+ temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
273+
274+ phong := TPhongShading.Create;
275+ phong.LightSourceDistanceFactor := 0;
276+ phong.LightDestFactor := 0;
277+ phong.LightSourceIntensity := 100;
278+ phong.LightPositionZ := 100;
279+ phong.NegativeDiffusionFactor := 0.3;
280+ phong.AmbientFactor := 0.5;
281+ phong.Draw(result,temp,30,-2,-2,BGRA(170,170,170));
282+
283+ phong.Free;
284+ temp.Free;
285+ end;
286+```
290287
291-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.
288+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.
292289
293-Now in the OnPaint event:
290+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.
294291
295-``` pascal
292+Now in the OnPaint event:
293+```
296294procedure TForm1.FormPaint(Sender: TObject);
297-var
298- image: TBGRABitmap;
299- stone: TBGRABitmap;
300-begin
301- image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
302-
303- stone := CreateStoneTexture(100,100);
304- image.FillEllipseAntialias(200,100,150,50,stone);
305- stone.free;
306-
307- image.Draw(Canvas,0,0,True);
308- image.free;
309-end;
295+ var
296+ image: TBGRABitmap;
297+ stone: TBGRABitmap;
298+ begin
299+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
300+
301+ stone := CreateStoneTexture(100,100);
302+ image.FillEllipseAntialias(200,100,150,50,stone);
303+ stone.free;
304+
305+ image.Draw(Canvas,0,0,True);
306+ image.free;
307+ end;
310308```
311309
312310### Run the program
313311
314-You should see a form with a stoned background.
312+You should see a form with a stoned background.
315313
316-<figure>
317-<img src="BGRATutorial9c.png" title="BGRATutorial9c.png" />
318-<figcaption>BGRATutorial9c.png</figcaption>
319-</figure>
314+[![BGRATutorial9c.png](/wiki-images/a/af/BGRATutorial9c.png)](</File:BGRATutorial9c.png>)
320315
321316### Rendering water
322317
323-It is almost the same procedure to generate water texture:
324-
325-``` pascal
318+It is almost the same procedure to generate water texture:
319+```
326320function CreateWaterTexture(tx,ty: integer): TBGRABitmap;
327-const blurSize = 5;
328-var
329- temp: TBGRABitmap;
330- phong: TPhongShading;
331-begin
332- result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
333- temp:= result.GetPart(rect(-blurSize,-blurSize,tx+blurSize,ty+blurSize)) as TBGRABitmap;
334- BGRAReplace(temp,temp.FilterBlurRadial(blurSize,rbFast));
335-
336- phong := TPhongShading.Create;
337- phong.LightSourceDistanceFactor := 0;
338- phong.LightDestFactor := 0;
339- phong.LightSourceIntensity := 150;
340- phong.LightPositionZ := 80;
341- phong.LightColor := BGRA(105,233,240);
342- phong.NegativeDiffusionFactor := 0.3;
343- phong.SpecularIndex := 20;
344- phong.AmbientFactor := 0.4;
345-
346- phong.Draw(result,temp,20,-blurSize,-blurSize,BGRA(28,139,166));
347- phong.Free;
348- temp.Free;
349-end;
321+ const blurSize = 5;
322+ var
323+ temp: TBGRABitmap;
324+ phong: TPhongShading;
325+ begin
326+ result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
327+ temp:= result.GetPart(rect(-blurSize,-blurSize,tx+blurSize,ty+blurSize)) as TBGRABitmap;
328+ BGRAReplace(temp,temp.FilterBlurRadial(blurSize,rbFast));
329+
330+ phong := TPhongShading.Create;
331+ phong.LightSourceDistanceFactor := 0;
332+ phong.LightDestFactor := 0;
333+ phong.LightSourceIntensity := 150;
334+ phong.LightPositionZ := 80;
335+ phong.LightColor := BGRA(105,233,240);
336+ phong.NegativeDiffusionFactor := 0.3;
337+ phong.SpecularIndex := 20;
338+ phong.AmbientFactor := 0.4;
339+
340+ phong.Draw(result,temp,20,-blurSize,-blurSize,BGRA(28,139,166));
341+ phong.Free;
342+ temp.Free;
343+ end;
350344```
351345
352-The main difference is that we apply a blur filter to make it the water smooth and set the light color.
346+The main difference is that we apply a blur filter to make it the water smooth and set the light color.
353347
354-<figure>
355-<img src="BGRATutorial9d.png" title="BGRATutorial9d.png" />
356-<figcaption>BGRATutorial9d.png</figcaption>
357-</figure>
348+[![BGRATutorial9d.png](/wiki-images/f/f1/BGRATutorial9d.png)](</File:BGRATutorial9d.png>)
358349
359350### Using thresholds to render snow prints
360351
361-It is possible to keep only a small subrange of altitudes, to have a texture that shows foot prints in the snow.
362-
363-``` pascal
352+It is possible to keep only a small subrange of altitudes, to have a texture that shows foot prints in the snow.
353+```
364354function CreateSnowPrintTexture(tx,ty: integer): TBGRABitmap;
365-var
366- v: integer;
367- p: PBGRAPixel;
368- i: Integer;
369-
370- temp: TBGRABitmap;
371- phong: TPhongShading;
372-begin
373- //here a random map is generated
374- result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
375-
376- //now we apply thresholds
377- p := result.Data;
378- for i := 0 to result.NbPixels-1 do
379- begin
380- v := p^.red;
381- //if the value is above 80 or under 50, then we divide it by 10 to make it almost horizontal
382- if v > 80 then v := (v-80) div 10+80;
383- if v < 50 then v := 50-(50-v) div 10;
384- p^.red := v;
385- p^.green := v;
386- p^.blue := v;
387- inc(p);
388- end;
389-
390- //to make phong shader aware of the cycle
391- temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
392- //apply a radial blur
393- BGRAReplace(temp,temp.FilterBlurRadial(2,rbFast));
394- phong := TPhongShading.Create;
395- phong.LightSourceDistanceFactor := 0;
396- phong.LightDestFactor := 0;
397- phong.LightSourceIntensity := 100;
398- phong.LightPositionZ := 100;
399- phong.NegativeDiffusionFactor := 0.3; //want shadows
400- phong.Draw(result,temp,30,-2,-2,BGRAWhite);
401- phong.Free;
402- temp.Free;
403-end;
355+ var
356+ v: integer;
357+ p: PBGRAPixel;
358+ i: Integer;
359+
360+ temp: TBGRABitmap;
361+ phong: TPhongShading;
362+ begin
363+ //here a random map is generated
364+ result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
365+
366+ //now we apply thresholds
367+ p := result.Data;
368+ for i := 0 to result.NbPixels-1 do
369+ begin
370+ v := p^.red;
371+ //if the value is above 80 or under 50, then we divide it by 10 to make it almost horizontal
372+ if v > 80 then v := (v-80) div 10+80;
373+ if v < 50 then v := 50-(50-v) div 10;
374+ p^.red := v;
375+ p^.green := v;
376+ p^.blue := v;
377+ inc(p);
378+ end;
379+
380+ //to make phong shader aware of the cycle
381+ temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
382+ //apply a radial blur
383+ BGRAReplace(temp,temp.FilterBlurRadial(2,rbFast));
384+ phong := TPhongShading.Create;
385+ phong.LightSourceDistanceFactor := 0;
386+ phong.LightDestFactor := 0;
387+ phong.LightSourceIntensity := 100;
388+ phong.LightPositionZ := 100;
389+ phong.NegativeDiffusionFactor := 0.3; //want shadows
390+ phong.Draw(result,temp,30,-2,-2,BGRAWhite);
391+ phong.Free;
392+ temp.Free;
393+ end;
404394```
405395
406-We obtain this:
396+We obtain this:
407397
408-<figure>
409-<img src="BGRATutorial9e.png" title="BGRATutorial9e.png" />
410-<figcaption>BGRATutorial9e.png</figcaption>
411-</figure>
398+[![BGRATutorial9e.png](/wiki-images/d/de/BGRATutorial9e.png)](</File:BGRATutorial9e.png>)
412399
413400[[BGRABitmap tutorial 8|Previous tutorial (textures)]] [[BGRABitmap tutorial 10|Next tutorial (texture mapping)]]
414401
415402---
416-*From the Free Pascal wiki, page "BGRABitmap tutorial 9", as it stood on 2020-01-02 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
417-Category: BGRABitmap
418-Category: Graphics
403+*From the Free Pascal wiki, page "BGRABitmap tutorial 9", as the Internet Archive kept it on 2024-11-04. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history