Sign in Join
Wiki copytemporary

BGRABitmap tutorial 8/es: what changed

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

OldNewLine
1-Esta tutoría muestra como usar texturas.
2-
3-### Crear un nuevo proyecto
4-
5-Crea un nuevo proyecto y añade referencia a [[BGRABitmap]], de la misma forma que en [[BGRABitmap tutorial/es|la primer tutoría]].
6-
7-### Usando pinceles de textura
8-
9-La textura mas simple es un pincel eclosionado.
1+[[BGRABitmap tutorial/es|**Home**]] | [[BGRABitmap tutorial 1/es|**Tutorial 1**]] | [[BGRABitmap tutorial 2/es|**Tutorial 2**]] | [[BGRABitmap tutorial 3/es|**Tutorial 3**]] | [[BGRABitmap tutorial 4/es|**Tutorial 4**]] | [[BGRABitmap tutorial 5/es|**Tutorial 5**]] | [[BGRABitmap tutorial 6/es|**Tutorial 6**]] | [[BGRABitmap tutorial 7/es|**Tutorial 7**]] | **Tutorial 8** | [[BGRABitmap tutorial 9/es|**Tutorial 9**]] | [[BGRABitmap tutorial 10/es|**Tutorial 10**]] | [[BGRABitmap tutorial 11/es|**Tutorial 11**]] | [[BGRABitmap tutorial 12/es|**Tutorial 12**]] | [Edit](<http://wiki.lazarus.freepascal.org/index.php?title=Template:BGRABitmap_tutorial_index/es&action=edit>)
102
11-Con el inspector de objetos, añade un manejador OnPaint y escribe :
3+Esta tutoría muestra como usar texturas.
124
13-``` pascal
14-procedure TForm1.FormPaint(Sender: TObject);
15-var
16- image,tex: TBGRABitmap;
17- c: TBGRAPixel;
18- x,y,rx,ry: single;
5+## Contents
196
20-begin
21- image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
22- c := ColorToBGRA(ColorToRGB(clWindowText));
7+ * 1 Crear un nuevo proyecto
8+ * 2 Usando pinceles de textura
9+ * 3 Ejecuta el programa
10+ * 4 Generating textures
11+ * 4.1 Basic Perlin noise map
12+ * 4.2 Changing color
13+ * 4.3 Using thresholds
14+ * 4.4 Sine function
15+ * 4.5 Wood texture
2316
24- //ellipse coordinates
25- x := 150;
26- y := 100;
27- rx := 100;
28- ry := 50;
17+### Crear un nuevo proyecto
2918
30- // carga un pincel "diagcross" con un patron blanco y fondo naranja
31- tex := image.CreateBrushTexture(bsDiagCross,BGRAWhite,BGRA(255,192,0)) as TBGRABitmap;
19+Crea un nuevo proyecto y añade referencia a [[BGRABitmap]], de la misma forma que en [[BGRABitmap tutorial/es|la primer tutoría]].
3220
33- image.FillEllipseAntialias(x,y,rx-0.5,ry-0.5,tex);
34- image.EllipseAntialias(x,y,rx,ry,c,1); //draw outline
21+### Usando pinceles de textura
3522
36- tex.Free;
23+La textura mas simple es un pincel eclosionado.
3724
38- image.Draw(Canvas,0,0,True);
39- image.free;
40-end;
25+Con el inspector de objetos, añade un manejador OnPaint y escribe :
4126```
42-
43-Como puedes ver, una textura es un bitmap. Para rellenar un elipse con una textura, pasa la textura como parametro en vez del color.
27+procedure TForm1.FormPaint(Sender: TObject);
28+ var
29+ image,tex: TBGRABitmap;
30+ c: TBGRAPixel;
31+ x,y,rx,ry: single;
32+
33+ begin
34+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
35+ c := ColorToBGRA(ColorToRGB(clWindowText));
36+
37+ //ellipse coordinates
38+ x := 150;
39+ y := 100;
40+ rx := 100;
41+ ry := 50;
42+
43+ // carga un pincel "diagcross" con un patron blanco y fondo naranja
44+ tex := image.CreateBrushTexture(bsDiagCross,BGRAWhite,BGRA(255,192,0)) as TBGRABitmap;
45+
46+ image.FillEllipseAntialias(x,y,rx-0.5,ry-0.5,tex);
47+ image.EllipseAntialias(x,y,rx,ry,c,1); //draw outline
48+
49+ tex.Free;
50+
51+ image.Draw(Canvas,0,0,True);
52+ image.free;
53+ end;
54+```
4455
45-Dos 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.
56+Como puedes ver, una textura es un bitmap. Para rellenar un elipse con una textura, pasa la textura como parametro en vez del color.
4657
47-Uso 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.
58+Dos 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.
4859
49-Agregue las líneas siguientes antes de tex.Free:
60+Uso 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.
5061
51-``` pascal
52- image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,c,11);
53- image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,tex,9);
62+Agregue las líneas siguientes antes de tex.Free:
5463```
64+image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,c,11);
65+ image.RoundRectAntialias(x-rx-10,y-ry-10,x+rx+10,y+ry+10,20,20,tex,9);
66+```
5567
56-El 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.
68+El 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.
5769
5870### Ejecuta el programa
5971
60-Deberías obtener un rectángulo redondeado con un elipse dentro. Cada capa está rellenada con una textura naranja.
72+Deberías obtener un rectángulo redondeado con un elipse dentro. Cada capa está rellenada con una textura naranja.
6173
62-![](/wiki-images/b/b7/BGRATutorial8.png)
74+[![BGRATutorial8.png](/wiki-images/b/b7/BGRATutorial8.png)](</File:BGRATutorial8.png>)
6375
6476### Generating textures
6577
6678#### Basic Perlin noise map
6779
68-It is possible to generate tilable random textures using CreateCyclicPerlinNoiseMap that can be found in the BGRAGradient unit.
69-
70-With the object inspector, define the OnPaint handler with :
80+It is possible to generate tilable random textures using CreateCyclicPerlinNoiseMap that can be found in the BGRAGradient unit.
7181
72-``` pascal
82+With the object inspector, define the OnPaint handler with :
83+```
7384procedure TForm1.FormPaint(Sender: TObject);
74-var
75- image,tex: TBGRABitmap;
76-
77-begin
78- image := TBGRABitmap.Create(ClientWidth,ClientHeight);
79-
80- tex := CreateCyclicPerlinNoiseMap(100,100);
81- image.FillRect(0,0,image.Width,image.Height, tex);
82- tex.free;
83-
84- image.Draw(Canvas,0,0,True);
85- image.free;
86-end;
85+ var
86+ image,tex: TBGRABitmap;
87+
88+ begin
89+ image := TBGRABitmap.Create(ClientWidth,ClientHeight);
90+
91+ tex := CreateCyclicPerlinNoiseMap(100,100);
92+ image.FillRect(0,0,image.Width,image.Height, tex);
93+ tex.free;
94+
95+ image.Draw(Canvas,0,0,True);
96+ image.free;
97+ end;
8798```
8899
89-This creates a 100x100 texture, and fills the form with it. You should obtain something like this :
100+This creates a 100x100 texture, and fills the form with it. You should obtain something like this :
90101
91-![](/wiki-images/3/3e/BGRATutorial8b.png)
102+[![BGRATutorial8b.png](/wiki-images/3/3e/BGRATutorial8b.png)](</File:BGRATutorial8b.png>)
92103
93104#### Changing color
94105
95-This is very black and white. We can add some colors. For this, we will need some function to interpolate values. Here it is :
96-
97-``` pascal
98- function Interp256(value1,value2,position: integer): integer; inline;
99- begin
100- result := (value1*(256-position) + value2*position) shr 8;
101- end;
106+This is very black and white. We can add some colors. For this, we will need some function to interpolate values. Here it is :
102107```
103-
104-This 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.
108+function Interp256(value1,value2,position: integer): integer; inline;
109+ begin
110+ result := (value1*(256-position) + value2*position) shr 8;
111+ end;
112+```
105113
106-We want to interpolate colors, so let's write a function to interpolate colors :
114+This 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.
107115
108-``` pascal
109- function Interp256(color1,color2: TBGRAPixel; position: integer): TBGRAPixel; inline;
110- begin
111- result.red := Interp256(color1.red,color2.red, position);
112- result.green := Interp256(color1.green,color2.green, position);
113- result.blue := Interp256(color1.blue,color2.blue, position);
114- result.alpha := Interp256(color1.alpha,color2.alpha, position);
115- end;
116+We want to interpolate colors, so let's write a function to interpolate colors :
116117```
117-
118-It is straightforward : each color component is interpolated between color1 and color2 values.
118+function Interp256(color1,color2: TBGRAPixel; position: integer): TBGRAPixel; inline;
119+ begin
120+ result.red := Interp256(color1.red,color2.red, position);
121+ result.green := Interp256(color1.green,color2.green, position);
122+ result.blue := Interp256(color1.blue,color2.blue, position);
123+ result.alpha := Interp256(color1.alpha,color2.alpha, position);
124+ end;
125+```
119126
120-Now we have everything to make some colors. After CreatePerlinNoiseMap, add the following lines :
127+It is straightforward : each color component is interpolated between color1 and color2 values.
121128
122-``` pascal
123- p := tex.Data;
124- for i := 0 to tex.NbPixels-1 do
125- begin
126- p^ := Interp256( BGRA(0,128,0), BGRA(192,255,0), p^.red );
127- inc(p);
128- end;
129+Now we have everything to make some colors. After CreatePerlinNoiseMap, add the following lines :
129130```
131+p := tex.Data;
132+ for i := 0 to tex.NbPixels-1 do
133+ begin
134+ p^ := Interp256( BGRA(0,128,0), BGRA(192,255,0), p^.red );
135+ inc(p);
136+ end;
137+```
130138
131-You'll need variables 'p' and 'i', so click on each and press Ctrl-Shift-C.
139+You'll need variables 'p' and 'i', so click on each and press Ctrl-Shift-C.
132140
133-This loop takes each pixel and creates a color from dark green to light green-yellow.
141+This loop takes each pixel and creates a color from dark green to light green-yellow.
134142
135-We obtain a tree-like green color :
143+We obtain a tree-like green color :
136144
137-![](/wiki-images/9/93/BGRATutorial8c.png)
145+[![BGRATutorial8c.png](/wiki-images/9/93/BGRATutorial8c.png)](</File:BGRATutorial8c.png>)
138146
139147#### Using thresholds
140148
141-Instead of varying continuously, the color can be changed with a threshold. For example, we can delimit sea and islands :
142-
143-``` pascal
144- p := tex.Data;
145- for i := 0 to tex.NbPixels-1 do
146- begin
147- if p^.red > 196 then
148- p^ := BGRA(192,160,96) else //island
149- p^ := BGRA(0,128,196); //sea
150- inc(p);
151- end;
149+Instead of varying continuously, the color can be changed with a threshold. For example, we can delimit sea and islands :
152150```
153-
154-We can use more thresholds. Here is a camouflage :
151+p := tex.Data;
152+ for i := 0 to tex.NbPixels-1 do
153+ begin
154+ if p^.red > 196 then
155+ p^ := BGRA(192,160,96) else //island
156+ p^ := BGRA(0,128,196); //sea
157+ inc(p);
158+ end;
159+```
155160
156-``` pascal
157- p := result.Data;
158- for i := 0 to result.NbPixels-1 do
159- begin
160- v := p^.red;
161- if v < 64 then p^:= BGRA(31,33,46) else
162- if v < 128 then p^:= BGRA(89,71,57) else
163- if v < 192 then p^:= BGRA(80,106,67) else
164- p^:= BGRA(161,157,121);
165- inc(p);
166- end;
161+We can use more thresholds. Here is a camouflage :
167162```
163+p := result.Data;
164+ for i := 0 to result.NbPixels-1 do
165+ begin
166+ v := p^.red;
167+ if v < 64 then p^:= BGRA(31,33,46) else
168+ if v < 128 then p^:= BGRA(89,71,57) else
169+ if v < 192 then p^:= BGRA(80,106,67) else
170+ p^:= BGRA(161,157,121);
171+ inc(p);
172+ end;
173+```
168174
169-![](/wiki-images/d/d6/BGRATutorial8d.png)
175+[![BGRATutorial8d.png](/wiki-images/d/d6/BGRATutorial8d.png)](</File:BGRATutorial8d.png>)
170176
171177#### Sine function
172178
173-We will apply here a sine function to noise values. Let's create a procedure for this :
174-
175-``` pascal
176- function CreateCustomTexture(tx,ty: integer): TBGRABitmap;
177- var
178- colorOscillation: integer;
179- p: PBGRAPixel;
180- i: Integer;
181- begin
182- result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1);
183- p := result.Data;
184- for i := 0 to result.NbPixels-1 do
185- begin
186- colorOscillation := round(((sin(p^.red*Pi/32)+1)/2)*256);
187- p^ := Interp256(BGRA(181,157,105),BGRA(228,227,180),colorOscillation);
188- inc(p);
189- end;
190- end;
179+We will apply here a sine function to noise values. Let's create a procedure for this :
191180```
192-
193-The 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.
181+function CreateCustomTexture(tx,ty: integer): TBGRABitmap;
182+ var
183+ colorOscillation: integer;
184+ p: PBGRAPixel;
185+ i: Integer;
186+ begin
187+ result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1);
188+ p := result.Data;
189+ for i := 0 to result.NbPixels-1 do
190+ begin
191+ colorOscillation := round(((sin(p^.red*Pi/32)+1)/2)*256);
192+ p^ := Interp256(BGRA(181,157,105),BGRA(228,227,180),colorOscillation);
193+ inc(p);
194+ end;
195+ end;
196+```
194197
195-The OnPaint procedure becomes simpler :
198+The 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.
196199
197-``` pascal
200+The OnPaint procedure becomes simpler :
201+```
198202var
199- image,tex: TBGRABitmap;
200-
201-begin
202- image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
203-
204- tex := CreateCustomTexture(100,100);
205- image.FillRoundRectAntialias(20,20,300,200,20,20,tex);
206- image.RoundRectAntialias(20,20,300,200,20,20,BGRABlack,1);
207- tex.free;
208-
209- image.Draw(Canvas,0,0,True);
210- image.free;
211-end;
203+ image,tex: TBGRABitmap;
204+
205+ begin
206+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
207+
208+ tex := CreateCustomTexture(100,100);
209+ image.FillRoundRectAntialias(20,20,300,200,20,20,tex);
210+ image.RoundRectAntialias(20,20,300,200,20,20,BGRABlack,1);
211+ tex.free;
212+
213+ image.Draw(Canvas,0,0,True);
214+ image.free;
215+ end;
212216```
213217
214-You should obtain something like this :
215-
216-![](/wiki-images/8/8c/BGRATutorial8e.png)
218+You should obtain something like this :
217219
218-Now, 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 :
220+[![BGRATutorial8e.png](/wiki-images/8/8c/BGRATutorial8e.png)](</File:BGRATutorial8e.png>)
219221
220-``` pascal
221- colorOscillation := round(power((sin(p^.red*Pi/80)+1)/2,0.2)*256);
222+Now, 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 :
222223```
224+colorOscillation := round(power((sin(p^.red*Pi/80)+1)/2,0.2)*256);
225+```
223226
224-Now we have something much more like marble :
227+Now we have something much more like marble :
225228
226-![](/wiki-images/9/95/BGRATutorial8f.png)
229+[![BGRATutorial8f.png](/wiki-images/9/95/BGRATutorial8f.png)](</File:BGRATutorial8f.png>)
227230
228231#### Wood texture
229232
230-Wood 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 :
231-
232-``` pascal
233- function CreateWoodTexture(tx,ty: integer): TBGRABitmap;
234- var
235- colorOscillation, globalColorVariation: integer;
236- p: PBGRAPixel;
237- i: Integer;
238- begin
239- result := CreateCyclicPerlinNoiseMap(tx,ty);
240- p := result.Data;
241- for i := 0 to result.NbPixels-1 do
242- begin
243- colorOscillation := round(sqrt((sin(p^.red*Pi/16)+1)/2)*256);
244- globalColorVariation := p^.red;
245- p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation),
246- Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation);
247- inc(p);
248- end;
249- end;
233+Wood 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 :
250234```
251-
252-Here the half-period is 16, and the global variation is simply the intensity. The result is something like this :
235+function CreateWoodTexture(tx,ty: integer): TBGRABitmap;
236+ var
237+ colorOscillation, globalColorVariation: integer;
238+ p: PBGRAPixel;
239+ i: Integer;
240+ begin
241+ result := CreateCyclicPerlinNoiseMap(tx,ty);
242+ p := result.Data;
243+ for i := 0 to result.NbPixels-1 do
244+ begin
245+ colorOscillation := round(sqrt((sin(p^.red*Pi/16)+1)/2)*256);
246+ globalColorVariation := p^.red;
247+ p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation),
248+ Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation);
249+ inc(p);
250+ end;
251+ end;
252+```
253253
254-![](/wiki-images/d/d0/BGRATutorial8g.png)
254+Here the half-period is 16, and the global variation is simply the intensity. The result is something like this :
255255
256-Most 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 :
256+[![BGRATutorial8g.png](/wiki-images/d/d0/BGRATutorial8g.png)](</File:BGRATutorial8g.png>)
257257
258-``` pascal
259- function CreateVerticalWoodTexture(tx,ty: integer): TBGRABitmap;
260- var
261- globalPos: single;
262- colorOscillation, globalColorVariation: integer;
263- p: PBGRAPixel;
264- i: Integer;
265- x: integer;
266- begin
267- result := CreateCyclicPerlinNoiseMap(tx,ty);
268- p := result.Data;
269- x := 0;
270- for i := 0 to result.NbPixels-1 do
271- begin
272- globalPos := p^.red*Pi/32+x*2*Pi/tx*8;
273- colorOscillation := round(sqrt((sin(globalPos)+1)/2)*256);
274- globalColorVariation := round(sin(globalPos/8)*128+128);
275- p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation),
276- Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation);
277- inc(p);
278- inc(x);
279- if x = tx then x := 0;
280- end;
281- end;
258+Most 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 :
282259```
260+function CreateVerticalWoodTexture(tx,ty: integer): TBGRABitmap;
261+ var
262+ globalPos: single;
263+ colorOscillation, globalColorVariation: integer;
264+ p: PBGRAPixel;
265+ i: Integer;
266+ x: integer;
267+ begin
268+ result := CreateCyclicPerlinNoiseMap(tx,ty);
269+ p := result.Data;
270+ x := 0;
271+ for i := 0 to result.NbPixels-1 do
272+ begin
273+ globalPos := p^.red*Pi/32+x*2*Pi/tx*8;
274+ colorOscillation := round(sqrt((sin(globalPos)+1)/2)*256);
275+ globalColorVariation := round(sin(globalPos/8)*128+128);
276+ p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation),
277+ Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation);
278+ inc(p);
279+ inc(x);
280+ if x = tx then x := 0;
281+ end;
282+ end;
283+```
283284
284-We obtain this :
285+We obtain this :
285286
286-![](/wiki-images/3/37/Tutorial8h.png)
287+[![Tutorial8h.png](/wiki-images/3/37/Tutorial8h.png)](</File:Tutorial8h.png>)
287288
288-[[BGRABitmap tutorial 7/es|Tutoría anterior (splines)]] \| [[BGRABitmap tutorial 9/es|Siguiente tutoría (phong shading y texturas)]]
289+
290+[[BGRABitmap tutorial 7/es|Tutoría anterior (splines)]] | [[BGRABitmap tutorial 9/es|Siguiente tutoría (phong shading y texturas)]]
289291
290292---
291-*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).*
292-Category: Castellano
293-Category: Español
293+*From the Free Pascal wiki, page "BGRABitmap tutorial 8/es", as the Internet Archive kept it on 2022-07-03. 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