Sign in Join
Wiki copytemporary

BGRABitmap tutorial 9: what changed

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

OldNewLine
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]]
2-
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
1+This tutorial shows how to use phong shading to make textures.
172
183### Create a new project
194
20-Create a new project and add a reference to [[BGRABitmap]], the same way as in [[BGRABitmap tutorial 1|the first tutorial]].
5+Create a new project and add a reference to [[BGRABitmap]], the same way as in [[BGRABitmap tutorial 1|the first tutorial]].
216
227### Phong shading and light
238
24-To use phong shading, you need to instanciate a TPhongShading class. It's located in BGRAGradients unit.
9+To use phong shading, you need to instanciate a TPhongShading class. It's located in BGRAGradients unit.
2510
26-Let's add a variable in the form definition:
27-```
11+Let's add a variable in the form definition:
12+
13+``` pascal
2814TForm1 = class(TForm)
29- ...
30- phong: TPhongShading;
15+ ...
16+ phong: TPhongShading;
3117```
3218
33-When the form is created, we can create the class:
34-```
19+When the form is created, we can create the class:
20+
21+``` pascal
3522procedure TForm1.FormCreate(Sender: TObject);
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;
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;
4431```
4532
46-The specular index indicates how concentrated the reflected light is.
33+The specular index indicates how concentrated the reflected light is.
4734
48-When the form is destroyed:
49-```
35+When the form is destroyed:
36+
37+``` pascal
5038procedure TForm1.FormDestroy(Sender: TObject);
51- begin
52- phong.Free;
53- end;
39+begin
40+ phong.Free;
41+end;
5442```
5543
56-When the form is painted, add some phong shaded object:
57-```
44+When the form is painted, add some phong shaded object:
45+
46+``` pascal
5847procedure TForm1.FormPaint(Sender: TObject);
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;
70-```
48+var
49+ image: TBGRABitmap;
7150
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.
51+begin
52+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
7353
74-Finally when the mouse is moved, it would be nice that the light source followed:
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;
7559```
60+
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:
64+
65+``` pascal
7666procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
77- Y: Integer);
78- begin
79- phong.LightPosition := point(X,Y);
80- FormPaint(Sender);
81- end;
67+ Y: Integer);
68+begin
69+ phong.LightPosition := point(X,Y);
70+ FormPaint(Sender);
71+end;
8272```
8373
8474### Run the program
8575
86-You should be able to play with the light on the sphere:
76+You should be able to play with the light on the sphere:
8777
88-[![BGRATutorial9a.png](/wiki-images/f/fd/BGRATutorial9a.png)](</File:BGRATutorial9a.png>)
78+![](/wiki-images/f/fd/BGRATutorial9a.png)
8979
9080### Use phong shading to create textures
9181
92-The following procedure creates a piece of chocolate:
93-```
82+The following procedure creates a piece of chocolate:
83+
84+``` pascal
9485function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
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;
128-```
86+var
87+ square,map: TBGRABitmap;
88+ phong: TPhongShading;
89+ margin: integer;
90+begin
91+ margin := tx div 20; //empty space around the square
92+ square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
12993
130-The phong shader uses a map of altitudes to render the light effects. Here, the map contains a square.
94+ //create a map with the square at the middle
95+ map := TBGRABitmap.Create(tx,ty,BGRABlack);
96+ map.PutImage(margin,margin,square,dmDrawWithTransparency);
13197
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.
98+ //apply blur to make it smoother
99+ BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
100+ square.free;
133101
134-Now, when the form is created, create the chocolate texture:
135-```
136-chocolate := CreateChocolateTexture(80,80);
137-```
102+ //create resulting bitmap
103+ result := TBGRABitmap.Create(tx,ty);
138104
139-And when the form is destroyed:
105+ //use phong shading
106+ phong := TPhongShading.Create;
107+ phong.LightSourceDistanceFactor := 0;
108+ phong.LightDestFactor := 0;
109+ phong.LightSourceIntensity := 200;
110+ phong.AmbientFactor := 0.5;
111+ phong.LightPosition := Point(-50,-100);
112+ phong.LightPositionZ := 80;
113+
114+ //draw the piece of chocolate with max altitude 20
115+ phong.Draw(result,map,20,0,0,BGRA(86,41,38));
116+ map.Free;
117+ phong.Free;
118+end;
140119```
141-chocolate.Free;
120+
121+The phong shader uses a map of altitudes to render the light effects. Here, the map contains a square.
122+
123+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.
124+
125+Now, when the form is created, create the chocolate texture:
126+
127+``` pascal
128+ chocolate := CreateChocolateTexture(80,80);
142129```
143130
144-Before phong.DrawSphere in the OnPaint event, add this line:
131+And when the form is destroyed:
132+
133+``` pascal
134+ chocolate.Free;
145135```
146-image.FillRect(0,0,80*7,80*4,chocolate,dmSet);
136+
137+Before phong.DrawSphere in the OnPaint event, add this line:
138+
139+``` pascal
140+ image.FillRect(0,0,80*7,80*4,chocolate,dmSet);
147141```
148142
149143### Resulting code
150-```
144+
145+``` pascal
151146unit UMain;
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.
147+
148+{$mode objfpc}{$H+}
149+
150+interface
151+
152+uses
153+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
154+ ExtCtrls, Buttons, BGRABitmap, BGRABitmapTypes, BGRAGradients;
155+
156+type
157+ { TForm1 }
158+
159+ TForm1 = class(TForm)
160+ Timer1: TTimer;
161+ procedure FormCreate(Sender: TObject);
162+ procedure FormDestroy(Sender: TObject);
163+ procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
164+ procedure FormPaint(Sender: TObject);
165+ private
166+ { private declarations }
167+ public
168+ { public declarations }
169+ phong: TPhongShading;
170+ chocolate: TBGRABitmap;
171+ end;
172+
173+var
174+ Form1: TForm1;
175+
176+implementation
177+
178+function CreateChocolateTexture(tx,ty: integer): TBGRABitmap;
179+var
180+ square,map: TBGRABitmap;
181+ phong: TPhongShading;
182+ margin: integer;
183+begin
184+ margin := tx div 20;
185+ square := CreateRectangleMap(tx-2*margin,ty-2*margin,tx div 8);
186+ map := TBGRABitmap.Create(tx,ty,BGRABlack);
187+ map.PutImage(margin,margin,square,dmDrawWithTransparency);
188+ BGRAReplace(map,map.FilterBlurRadial(tx div 40,rbFast));
189+ square.free;
190+
191+ result := TBGRABitmap.Create(tx,ty);
192+ phong := TPhongShading.Create;
193+ phong.LightSourceDistanceFactor := 0;
194+ phong.LightDestFactor := 0;
195+ phong.LightSourceIntensity := 200;
196+ phong.AmbientFactor := 0.5;
197+ phong.LightPosition := Point(-50,-100);
198+ phong.LightPositionZ := 80;
199+ phong.Draw(result,map,20,0,0,BGRA(86,41,38));
200+ map.Free;
201+ phong.Free;
202+end;
203+
204+{ TForm1 }
205+
206+procedure TForm1.FormCreate(Sender: TObject);
207+begin
208+ phong := TPhongShading.Create;
209+ phong.LightPositionZ := 150;
210+ phong.SpecularIndex := 20;
211+ phong.AmbientFactor := 0.4;
212+ phong.LightSourceIntensity := 250;
213+ phong.LightSourceDistanceTerm := 200;
214+
215+ chocolate := CreateChocolateTexture(80,80);
216+end;
217+
218+procedure TForm1.FormDestroy(Sender: TObject);
219+begin
220+ phong.Free;
221+ chocolate.Free;
222+end;
223+
224+procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
225+ Y: Integer);
226+begin
227+ phong.LightPosition := point(X,Y);
228+ FormPaint(Sender);
229+end;
230+
231+procedure TForm1.FormPaint(Sender: TObject);
232+var
233+ image: TBGRABitmap;
234+begin
235+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
236+
237+ image.FillRect(0,0,80*7,80*4,chocolate,dmSet);
238+ phong.DrawSphere(image,rect(20,20,120,120),50,BGRA(255,0,0));
239+
240+ image.Draw(Canvas,0,0,True);
241+ image.free;
242+end;
243+
244+initialization
245+ {$I UMain.lrs}
246+
247+end.
254248```
255249
256250### Run the program
257251
258-You should see a nice bar of chocolate with a big cherry:
252+You should see a nice bar of chocolate with a big cherry:
259253
260-[![BGRATutorial9b.png](/wiki-images/6/6f/BGRATutorial9b.png)](</File:BGRATutorial9b.png>)
254+![](/wiki-images/6/6f/BGRATutorial9b.png)
261255
262256### Using Perlin noise and phong shading together
263257
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-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-```
258+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:
287259
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.
260+``` pascal
261+ function CreateStoneTexture(tx,ty: integer): TBGRABitmap;
262+ var
263+ temp: TBGRABitmap;
264+ phong: TPhongShading;
265+ begin
266+ result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,0.6);
267+ temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
289268
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.
269+ phong := TPhongShading.Create;
270+ phong.LightSourceDistanceFactor := 0;
271+ phong.LightDestFactor := 0;
272+ phong.LightSourceIntensity := 100;
273+ phong.LightPositionZ := 100;
274+ phong.NegativeDiffusionFactor := 0.3;
275+ phong.AmbientFactor := 0.5;
276+ phong.Draw(result,temp,30,-2,-2,BGRA(170,170,170));
291277
292-Now in the OnPaint event:
278+ phong.Free;
279+ temp.Free;
280+ end;
293281```
282+
283+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.
284+
285+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.
286+
287+Now in the OnPaint event:
288+
289+``` pascal
294290procedure TForm1.FormPaint(Sender: TObject);
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;
291+var
292+ image: TBGRABitmap;
293+ stone: TBGRABitmap;
294+begin
295+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
296+
297+ stone := CreateStoneTexture(100,100);
298+ image.FillEllipseAntialias(200,100,150,50,stone);
299+ stone.free;
300+
301+ image.Draw(Canvas,0,0,True);
302+ image.free;
303+end;
308304```
309305
310306### Run the program
311307
312-You should see a form with a stoned background.
308+You should see a form with a stoned background.
313309
314-[![BGRATutorial9c.png](/wiki-images/a/af/BGRATutorial9c.png)](</File:BGRATutorial9c.png>)
310+![](/wiki-images/a/af/BGRATutorial9c.png)
315311
316312### Rendering water
317313
318-It is almost the same procedure to generate water texture:
319-```
314+It is almost the same procedure to generate water texture:
315+
316+``` pascal
320317function CreateWaterTexture(tx,ty: integer): TBGRABitmap;
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;
318+const blurSize = 5;
319+var
320+ temp: TBGRABitmap;
321+ phong: TPhongShading;
322+begin
323+ result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
324+ temp:= result.GetPart(rect(-blurSize,-blurSize,tx+blurSize,ty+blurSize)) as TBGRABitmap;
325+ BGRAReplace(temp,temp.FilterBlurRadial(blurSize,rbFast));
326+
327+ phong := TPhongShading.Create;
328+ phong.LightSourceDistanceFactor := 0;
329+ phong.LightDestFactor := 0;
330+ phong.LightSourceIntensity := 150;
331+ phong.LightPositionZ := 80;
332+ phong.LightColor := BGRA(105,233,240);
333+ phong.NegativeDiffusionFactor := 0.3;
334+ phong.SpecularIndex := 20;
335+ phong.AmbientFactor := 0.4;
336+
337+ phong.Draw(result,temp,20,-blurSize,-blurSize,BGRA(28,139,166));
338+ phong.Free;
339+ temp.Free;
340+end;
344341```
345342
346-The main difference is that we apply a blur filter to make it the water smooth and set the light color.
343+The main difference is that we apply a blur filter to make it the water smooth and set the light color.
347344
348-[![BGRATutorial9d.png](/wiki-images/f/f1/BGRATutorial9d.png)](</File:BGRATutorial9d.png>)
345+![](/wiki-images/f/f1/BGRATutorial9d.png)
349346
350347### Using thresholds to render snow prints
351348
352-It is possible to keep only a small subrange of altitudes, to have a texture that shows foot prints in the snow.
353-```
349+It is possible to keep only a small subrange of altitudes, to have a texture that shows foot prints in the snow.
350+
351+``` pascal
354352function CreateSnowPrintTexture(tx,ty: integer): TBGRABitmap;
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;
353+var
354+ v: integer;
355+ p: PBGRAPixel;
356+ i: Integer;
357+
358+ temp: TBGRABitmap;
359+ phong: TPhongShading;
360+begin
361+ //here a random map is generated
362+ result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1.2);
363+
364+ //now we apply thresholds
365+ p := result.Data;
366+ for i := 0 to result.NbPixels-1 do
367+ begin
368+ v := p^.red;
369+ //if the value is above 80 or under 50, then we divide it by 10 to make it almost horizontal
370+ if v > 80 then v := (v-80) div 10+80;
371+ if v < 50 then v := 50-(50-v) div 10;
372+ p^.red := v;
373+ p^.green := v;
374+ p^.blue := v;
375+ inc(p);
376+ end;
377+
378+ //to make phong shader aware of the cycle
379+ temp:= result.GetPart(rect(-2,-2,tx+2,ty+2)) as TBGRABitmap;
380+ //apply a radial blur
381+ BGRAReplace(temp,temp.FilterBlurRadial(2,rbFast));
382+ phong := TPhongShading.Create;
383+ phong.LightSourceDistanceFactor := 0;
384+ phong.LightDestFactor := 0;
385+ phong.LightSourceIntensity := 100;
386+ phong.LightPositionZ := 100;
387+ phong.NegativeDiffusionFactor := 0.3; //want shadows
388+ phong.Draw(result,temp,30,-2,-2,BGRAWhite);
389+ phong.Free;
390+ temp.Free;
391+end;
394392```
395393
396-We obtain this:
394+We obtain this:
397395
398-[![BGRATutorial9e.png](/wiki-images/d/de/BGRATutorial9e.png)](</File:BGRATutorial9e.png>)
396+![](/wiki-images/d/de/BGRATutorial9e.png)
399397
400398[[BGRABitmap tutorial 8|Previous tutorial (textures)]] [[BGRABitmap tutorial 10|Next tutorial (texture mapping)]]
401399
402400---
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).*
401+*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).*
402+Category: BGRABitmap
403+Category: Graphics

Back to history