Sign in Join
Wiki copytemporary

BGRABitmap tutorial 8/es: what changed

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

OldNewLine
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>)
2-
3-Esta tutoría muestra como usar texturas.
4-
5-## Contents
6-
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
1+Esta tutoría muestra como usar texturas.
162
173### Crear un nuevo proyecto
184
19-Crea un nuevo proyecto y añade referencia a [[BGRABitmap]], de la misma forma que en [[BGRABitmap tutorial/es|la primer tutoría]].
5+Crea un nuevo proyecto y añade referencia a [[BGRABitmap]], de la misma forma que en [[BGRABitmap tutorial/es|la primer tutoría]].
206
217### Usando pinceles de textura
228
23-La textura mas simple es un pincel eclosionado.
9+La textura mas simple es un pincel eclosionado.
2410
25-Con el inspector de objetos, añade un manejador OnPaint y escribe :
26-```
11+Con el inspector de objetos, añade un manejador OnPaint y escribe :
12+
13+``` pascal
2714procedure 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-```
15+var
16+ image,tex: TBGRABitmap;
17+ c: TBGRAPixel;
18+ x,y,rx,ry: single;
5519
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.
20+begin
21+ image := TBGRABitmap.Create(ClientWidth,ClientHeight,ColorToBGRA(ColorToRGB(clBtnFace)));
22+ c := ColorToBGRA(ColorToRGB(clWindowText));
5723
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.
24+ //ellipse coordinates
25+ x := 150;
26+ y := 100;
27+ rx := 100;
28+ ry := 50;
5929
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.
30+ // carga un pincel "diagcross" con un patron blanco y fondo naranja
31+ tex := image.CreateBrushTexture(bsDiagCross,BGRAWhite,BGRA(255,192,0)) as TBGRABitmap;
6132
62-Agregue las líneas siguientes antes de tex.Free:
33+ image.FillEllipseAntialias(x,y,rx-0.5,ry-0.5,tex);
34+ image.EllipseAntialias(x,y,rx,ry,c,1); //draw outline
35+
36+ tex.Free;
37+
38+ image.Draw(Canvas,0,0,True);
39+ image.free;
40+end;
6341```
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);
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.
44+
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.
46+
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.
48+
49+Agregue las líneas siguientes antes de tex.Free:
50+
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);
6654```
6755
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.
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.
6957
7058### Ejecuta el programa
7159
72-Deberías obtener un rectángulo redondeado con un elipse dentro. Cada capa está rellenada con una textura naranja.
60+Deberías obtener un rectángulo redondeado con un elipse dentro. Cada capa está rellenada con una textura naranja.
7361
74-[![BGRATutorial8.png](/wiki-images/b/b7/BGRATutorial8.png)](</File:BGRATutorial8.png>)
62+![](/wiki-images/b/b7/BGRATutorial8.png)
7563
7664### Generating textures
7765
7866#### Basic Perlin noise map
7967
80-It is possible to generate tilable random textures using CreateCyclicPerlinNoiseMap that can be found in the BGRAGradient unit.
68+It is possible to generate tilable random textures using CreateCyclicPerlinNoiseMap that can be found in the BGRAGradient unit.
8169
82-With the object inspector, define the OnPaint handler with :
83-```
70+With the object inspector, define the OnPaint handler with :
71+
72+``` pascal
8473procedure TForm1.FormPaint(Sender: TObject);
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;
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;
9887```
9988
100-This creates a 100x100 texture, and fills the form with it. You should obtain something like this :
89+This creates a 100x100 texture, and fills the form with it. You should obtain something like this :
10190
102-[![BGRATutorial8b.png](/wiki-images/3/3e/BGRATutorial8b.png)](</File:BGRATutorial8b.png>)
91+![](/wiki-images/3/3e/BGRATutorial8b.png)
10392
10493#### Changing color
10594
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 :
107-```
108-function Interp256(value1,value2,position: integer): integer; inline;
109- begin
110- result := (value1*(256-position) + value2*position) shr 8;
111- end;
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;
112102```
113103
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.
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.
115105
116-We want to interpolate colors, so let's write a function to interpolate colors :
117-```
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;
106+We want to interpolate colors, so let's write a function to interpolate colors :
107+
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;
125116```
126117
127-It is straightforward : each color component is interpolated between color1 and color2 values.
118+It is straightforward : each color component is interpolated between color1 and color2 values.
128119
129-Now we have everything to make some colors. After CreatePerlinNoiseMap, add the following lines :
130-```
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;
120+Now we have everything to make some colors. After CreatePerlinNoiseMap, add the following lines :
121+
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;
137129```
138130
139-You'll need variables 'p' and 'i', so click on each and press Ctrl-Shift-C.
131+You'll need variables 'p' and 'i', so click on each and press Ctrl-Shift-C.
140132
141-This loop takes each pixel and creates a color from dark green to light green-yellow.
133+This loop takes each pixel and creates a color from dark green to light green-yellow.
142134
143-We obtain a tree-like green color :
135+We obtain a tree-like green color :
144136
145-[![BGRATutorial8c.png](/wiki-images/9/93/BGRATutorial8c.png)](</File:BGRATutorial8c.png>)
137+![](/wiki-images/9/93/BGRATutorial8c.png)
146138
147139#### Using thresholds
148140
149-Instead of varying continuously, the color can be changed with a threshold. For example, we can delimit sea and islands :
150-```
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-```
141+Instead of varying continuously, the color can be changed with a threshold. For example, we can delimit sea and islands :
160142
161-We can use more thresholds. Here is a camouflage :
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;
162152```
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;
153+
154+We can use more thresholds. Here is a camouflage :
155+
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;
173167```
174168
175-[![BGRATutorial8d.png](/wiki-images/d/d6/BGRATutorial8d.png)](</File:BGRATutorial8d.png>)
169+![](/wiki-images/d/d6/BGRATutorial8d.png)
176170
177171#### Sine function
178172
179-We will apply here a sine function to noise values. Let's create a procedure for this :
180-```
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-```
197-
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.
173+We will apply here a sine function to noise values. Let's create a procedure for this :
199174
200-The OnPaint procedure becomes simpler :
201-```
202-var
203- image,tex: TBGRABitmap;
204-
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
205185 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;
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);
215189 end;
190+ end;
216191```
217192
218-You should obtain something like this :
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.
219194
220-[![BGRATutorial8e.png](/wiki-images/8/8c/BGRATutorial8e.png)](</File:BGRATutorial8e.png>)
195+The OnPaint procedure becomes simpler :
221196
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 :
197+``` pascal
198+var
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;
223212```
224-colorOscillation := round(power((sin(p^.red*Pi/80)+1)/2,0.2)*256);
213+
214+You should obtain something like this :
215+
216+![](/wiki-images/8/8c/BGRATutorial8e.png)
217+
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 :
219+
220+``` pascal
221+ colorOscillation := round(power((sin(p^.red*Pi/80)+1)/2,0.2)*256);
225222```
226223
227-Now we have something much more like marble :
224+Now we have something much more like marble :
228225
229-[![BGRATutorial8f.png](/wiki-images/9/95/BGRATutorial8f.png)](</File:BGRATutorial8f.png>)
226+![](/wiki-images/9/95/BGRATutorial8f.png)
230227
231228#### Wood texture
232229
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 :
234-```
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;
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;
252250```
253251
254-Here the half-period is 16, and the global variation is simply the intensity. The result is something like this :
252+Here the half-period is 16, and the global variation is simply the intensity. The result is something like this :
255253
256-[![BGRATutorial8g.png](/wiki-images/d/d0/BGRATutorial8g.png)](</File:BGRATutorial8g.png>)
254+![](/wiki-images/d/d0/BGRATutorial8g.png)
257255
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 :
259-```
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;
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 :
257+
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;
283282```
284283
285-We obtain this :
284+We obtain this :
286285
287-[![Tutorial8h.png](/wiki-images/3/37/Tutorial8h.png)](</File:Tutorial8h.png>)
286+![](/wiki-images/3/37/Tutorial8h.png)
288287
289-
290-[[BGRABitmap tutorial 7/es|Tutoría anterior (splines)]] | [[BGRABitmap tutorial 9/es|Siguiente tutoría (phong shading y texturas)]]
288+[[BGRABitmap tutorial 7/es|Tutoría anterior (splines)]] \| [[BGRABitmap tutorial 9/es|Siguiente tutoría (phong shading y texturas)]]
291289
292290---
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).*
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

Back to history