Sign in Join
Wiki copytemporary

BGRABitmap tutorial 8/es: what changed

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

OldNewLine
11Esta tutoría muestra como usar texturas.
22
33### Crear un nuevo proyecto
44
55Crea un nuevo proyecto y añade referencia a [[BGRABitmap]], de la misma forma que en [[BGRABitmap tutorial/es|la primer tutoría]].
66
77### Usando pinceles de textura
88
99La textura mas simple es un pincel eclosionado.
1010
1111Con el inspector de objetos, añade un manejador OnPaint y escribe :
1212
1313``` pascal
1414procedure TForm1.FormPaint(Sender: TObject);
1515var
1616 image,tex: TBGRABitmap;
1717 c: TBGRAPixel;
1818 x,y,rx,ry: single;
1919
2020begin
2121 image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
2222 c := ColorToBGRA(ColorToRGB(clWindowText));
2323
2424 //ellipse coordinates
2525 x := 150;
2626 y := 100;
2727 rx := 100;
2828 ry := 50;
2929
3030 // carga un pincel "diagcross" con un patron blanco y fondo naranja
3131 tex := image.CreateBrushTexture(bsDiagCross,BGRAWhite,BGRA(255,192,0)) as TBGRABitmap;
3232
3333 image.FillEllipseAntialias(x,y,rx-0.5,ry-0.5,tex);
3434 image.EllipseAntialias(x,y,rx,ry,c,1); //draw outline
3535
3636 tex.Free;
3737
3838 image.Draw(Canvas,0,0,True);
3939 image.free;
4040end;
4141```
4242
4343Como puedes ver, una textura es un bitmap. Para rellenar un elipse con una textura, pasa la textura como parametro en vez del color.
4444
4545Dos comandos definen el elipse. El primero es el rellenado, y el segundo el contorno. Ten en cuenta que el radio es 0.5 píxeles mas pequeños que el rellenado. De todas fromas, cuando el ancho de la pluma es 1, el radio interior es 0.5 mas pequeño y el radio exterior es 0.5 mas grande. Sin embargo, incluso si se presta atención a esto, el resultado no será perfecto. Si desea una unión suavizado entre polígonos, es necesario utilizar TBGRAMultishapeFiller en la unidad de BGRAPolygon y sacar todo de una vez.
4646
4747Uso de un comando para el esquema, logramos establecer una elipse con textura con un borde. Pero si la función de esquema no está disponible, también puede utilizar otro comando se llenan de un radio mayor con el color del borde, y luego un radio más pequeño para el interior.
4848
4949Agregue las líneas siguientes antes de tex.Free:
5050
5151``` pascal
5252 image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,c,11);
5353 image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,tex,9);
5454```
5555
5656El primer comando dibuja un rectángulo alrededor de ancho (ancho de 11) que incluye la frontera. El segundo comando se llenan de la textura con un ancho menor (9). Esto funciona perfectamente, siempre y cuando la textura no es transparente.
5757
5858### Ejecuta el programa
5959
6060Deberías obtener un rectángulo redondeado con un elipse dentro. Cada capa está rellenada con una textura naranja.
6161
62-<figure>
63-<img src="BGRATutorial8.png" title="BGRATutorial8.png" />
64-<figcaption>BGRATutorial8.png</figcaption>
65-</figure>
62+![](/wiki-images/b/b7/BGRATutorial8.png)
6663
6764### Generating textures
6865
6966#### Basic Perlin noise map
7067
7168It is possible to generate tilable random textures using CreateCyclicPerlinNoiseMap that can be found in the BGRAGradient unit.
7269
7370With the object inspector, define the OnPaint handler with :
7471
7572``` pascal
7673procedure TForm1.FormPaint(Sender: TObject);
7774var
7875 image,tex: TBGRABitmap;
7976
8077begin
8178 image := TBGRABitmap.Create(ClientWidth,ClientHeight);
8279
8380 tex := CreateCyclicPerlinNoiseMap(100,100);
8481 image.FillRect(0,0,image.Width,image.Height, tex);
8582 tex.free;
8683
8784 image.Draw(Canvas,0,0,True);
8885 image.free;
8986end;
9087```
9188
9289This creates a 100x100 texture, and fills the form with it. You should obtain something like this :
9390
94-<figure>
95-<img src="BGRATutorial8b.png" title="BGRATutorial8b.png" />
96-<figcaption>BGRATutorial8b.png</figcaption>
97-</figure>
91+![](/wiki-images/3/3e/BGRATutorial8b.png)
9892
9993#### Changing color
10094
10195This is very black and white. We can add some colors. For this, we will need some function to interpolate values. Here it is :
10296
10397``` pascal
10498 function Interp256(value1,value2,position: integer): integer; inline;
10599 begin
106100 result := (value1*(256-position) + value2*position) shr 8;
107101 end;
108102```
109103
110104This function computes a value going from value1 to value2. Position is a number between 0 and 256 which indicates how close the result is to the second value. The expression "shr 8" is an optimized equivalent to "div 256" for positive values. It is a binary shift of 8 digits.
111105
112106We want to interpolate colors, so let's write a function to interpolate colors :
113107
114108``` pascal
115109 function Interp256(color1,color2: TBGRAPixel; position: integer): TBGRAPixel; inline;
116110 begin
117111 result.red := Interp256(color1.red,color2.red, position);
118112 result.green := Interp256(color1.green,color2.green, position);
119113 result.blue := Interp256(color1.blue,color2.blue, position);
120114 result.alpha := Interp256(color1.alpha,color2.alpha, position);
121115 end;
122116```
123117
124118It is straightforward : each color component is interpolated between color1 and color2 values.
125119
126120Now we have everything to make some colors. After CreatePerlinNoiseMap, add the following lines :
127121
128122``` pascal
129123 p := tex.Data;
130124 for i := 0 to tex.NbPixels-1 do
131125 begin
132126 p^ := Interp256( BGRA(0,128,0), BGRA(192,255,0), p^.red );
133127 inc(p);
134128 end;
135129```
136130
137131You'll need variables 'p' and 'i', so click on each and press Ctrl-Shift-C.
138132
139133This loop takes each pixel and creates a color from dark green to light green-yellow.
140134
141135We obtain a tree-like green color :
142136
143-<figure>
144-<img src="BGRATutorial8c.png" title="BGRATutorial8c.png" />
145-<figcaption>BGRATutorial8c.png</figcaption>
146-</figure>
137+![](/wiki-images/9/93/BGRATutorial8c.png)
147138
148139#### Using thresholds
149140
150141Instead of varying continuously, the color can be changed with a threshold. For example, we can delimit sea and islands :
151142
152143``` pascal
153144 p := tex.Data;
154145 for i := 0 to tex.NbPixels-1 do
155146 begin
156147 if p^.red > 196 then
157148 p^ := BGRA(192,160,96) else //island
158149 p^ := BGRA(0,128,196); //sea
159150 inc(p);
160151 end;
161152```
162153
163154We can use more thresholds. Here is a camouflage :
164155
165156``` pascal
166157 p := result.Data;
167158 for i := 0 to result.NbPixels-1 do
168159 begin
169160 v := p^.red;
170161 if v < 64 then p^:= BGRA(31,33,46) else
171162 if v < 128 then p^:= BGRA(89,71,57) else
172163 if v < 192 then p^:= BGRA(80,106,67) else
173164 p^:= BGRA(161,157,121);
174165 inc(p);
175166 end;
176167```
177168
178-<figure>
179-<img src="BGRATutorial8d.png" title="BGRATutorial8d.png" />
180-<figcaption>BGRATutorial8d.png</figcaption>
181-</figure>
169+![](/wiki-images/d/d6/BGRATutorial8d.png)
182170
183171#### Sine function
184172
185173We will apply here a sine function to noise values. Let's create a procedure for this :
186174
187175``` pascal
188176 function CreateCustomTexture(tx,ty: integer): TBGRABitmap;
189177 var
190178 colorOscillation: integer;
191179 p: PBGRAPixel;
192180 i: Integer;
193181 begin
194182 result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1);
195183 p := result.Data;
196184 for i := 0 to result.NbPixels-1 do
197185 begin
198186 colorOscillation := round(((sin(p^.red*Pi/32)+1)/2)*256);
199187 p^ := Interp256(BGRA(181,157,105),BGRA(228,227,180),colorOscillation);
200188 inc(p);
201189 end;
202190 end;
203191```
204192
205193The color oscillation is a value between 0 and 256. It is calculated out of the intensity (p^.red). Here we apply a sine function with a half-period of 32. This gives a number between -1 and 1. To put it in the range 0..1, we add 1 and divide by 2. Finally, we multiply by 256 to have an integer for Interp256.
206194
207195The OnPaint procedure becomes simpler :
208196
209197``` pascal
210198var
211199 image,tex: TBGRABitmap;
212200
213201begin
214202 image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
215203
216204 tex := CreateCustomTexture(100,100);
217205 image.FillRoundRectAntialias(20,20,300,200,20,20,tex);
218206 image.RoundRectAntialias(20,20,300,200,20,20,BGRABlack,1);
219207 tex.free;
220208
221209 image.Draw(Canvas,0,0,True);
222210 image.free;
223211end;
224212```
225213
226214You should obtain something like this :
227215
228-<figure>
229-<img src="BGRATutorial8e.png" title="BGRATutorial8e.png" />
230-<figcaption>BGRATutorial8e.png</figcaption>
231-</figure>
216+![](/wiki-images/8/8c/BGRATutorial8e.png)
232217
233218Now, if we want it to look like marble, we need less oscillations. For example, we can use a half-period of 80. On marble, the black parts are very thin. We can distort the oscillation by applying the power function : an exponent between 0 and 1 will make the values closer to 1 and an exponent greater than 1 will make the values closer to 0. Let's change the oscillation like this in CreateCustomTexture :
234219
235220``` pascal
236221 colorOscillation := round(power((sin(p^.red*Pi/80)+1)/2,0.2)*256);
237222```
238223
239224Now we have something much more like marble :
240225
241-<figure>
242-<img src="BGRATutorial8f.png" title="BGRATutorial8f.png" />
243-<figcaption>BGRATutorial8f.png</figcaption>
244-</figure>
226+![](/wiki-images/9/95/BGRATutorial8f.png)
245227
246228#### Wood texture
247229
248230Wood texture can be achieved with sine functions too. Wood texture contains two oscillations, one with light colors, and another one with dark colors. So we need to apply a global variation between these oscillations :
249231
250232``` pascal
251233 function CreateWoodTexture(tx,ty: integer): TBGRABitmap;
252234 var
253235 colorOscillation, globalColorVariation: integer;
254236 p: PBGRAPixel;
255237 i: Integer;
256238 begin
257239 result := CreateCyclicPerlinNoiseMap(tx,ty);
258240 p := result.Data;
259241 for i := 0 to result.NbPixels-1 do
260242 begin
261243 colorOscillation := round(sqrt((sin(p^.red*Pi/16)+1)/2)*256);
262244 globalColorVariation := p^.red;
263245 p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation),
264246 Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation);
265247 inc(p);
266248 end;
267249 end;
268250```
269251
270252Here the half-period is 16, and the global variation is simply the intensity. The result is something like this :
271253
272-<figure>
273-<img src="BGRATutorial8g.png" title="BGRATutorial8g.png" />
274-<figcaption>BGRATutorial8g.png</figcaption>
275-</figure>
254+![](/wiki-images/d/d0/BGRATutorial8g.png)
276255
277256Most of the time, a wood texture is oriented along an axis. To do this, instead of using intensity only as a global position, we need to combine it with the x position :
278257
279258``` pascal
280259 function CreateVerticalWoodTexture(tx,ty: integer): TBGRABitmap;
281260 var
282261 globalPos: single;
283262 colorOscillation, globalColorVariation: integer;
284263 p: PBGRAPixel;
285264 i: Integer;
286265 x: integer;
287266 begin
288267 result := CreateCyclicPerlinNoiseMap(tx,ty);
289268 p := result.Data;
290269 x := 0;
291270 for i := 0 to result.NbPixels-1 do
292271 begin
293272 globalPos := p^.red*Pi/32+x*2*Pi/tx*8;
294273 colorOscillation := round(sqrt((sin(globalPos)+1)/2)*256);
295274 globalColorVariation := round(sin(globalPos/8)*128+128);
296275 p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation),
297276 Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation);
298277 inc(p);
299278 inc(x);
300279 if x = tx then x := 0;
301280 end;
302281 end;
303282```
304283
305284We obtain this :
306285
307-<figure>
308-<img src="Tutorial8h.png" title="Tutorial8h.png" />
309-<figcaption>Tutorial8h.png</figcaption>
310-</figure>
286+![](/wiki-images/3/37/Tutorial8h.png)
311287
312288[[BGRABitmap tutorial 7/es|Tutoría anterior (splines)]] \| [[BGRABitmap tutorial 9/es|Siguiente tutoría (phong shading y texturas)]]
313289
314290---
315291*From the Free Pascal wiki, page "BGRABitmap tutorial 8/es", as it stood on 2020-02-10 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).*
316292Category: Castellano
317293Category: Español

Back to history