BGRABitmap tutorial 16/de: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: BGRABitmap tutorial 16/de
| Old | New | Line | |
|---|---|---|---|
| 1 | + | Dieses Tutorial zeigt Ihnen, wie Sie Texturen an 3D-Objekten anwenden. | |
| 2 | + | ||
| 3 | + | ## Texturen erzeugen | |
| 4 | + | ||
| 5 | + | Zum Erzeugen der Texturen, benutzen wir die folgende Unit. Wie diese funktioniert, können Sie im [[BGRABitmap tutorial 8/de|Texturen-Tutorial]] nachlesen. Hier ist die Unit : | |
| 6 | + | ||
| 7 | + | ``` pascal | |
| 8 | + | unit utexture; | |
| 9 | + | ||
| 10 | + | {$mode objfpc}{$H+} | |
| 11 | + | ||
| 12 | + | interface | |
| 13 | + | ||
| 14 | + | uses | |
| 15 | + | Classes, SysUtils, BGRABitmap, BGRABitmapTypes; | |
| 16 | + | ||
| 17 | + | function CreateGrassTexture(tx,ty: integer): TBGRABitmap; | |
| 18 | + | function CreateVerticalWoodTexture(tx, ty: integer): TBGRABitmap; | |
| 19 | + | function CreateWoodTexture(tx,ty: integer): TBGRABitmap; | |
| 20 | + | ||
| 21 | + | implementation | |
| 22 | + | ||
| 23 | + | uses BGRAGradients; | |
| 24 | + | ||
| 25 | + | function Interp256(value1,value2,position: integer): integer; inline; | |
| 26 | + | begin | |
| 27 | + | result := (value1*(256-position)+value2*position) shr 8; | |
| 28 | + | end; | |
| 29 | + | ||
| 30 | + | function Interp256(color1,color2: TBGRAPixel; position: integer): TBGRAPixel; inline; | |
| 31 | + | begin | |
| 32 | + | result.red := Interp256(color1.red,color2.red,position); | |
| 33 | + | result.green := Interp256(color1.green,color2.green,position); | |
| 34 | + | result.blue := Interp256(color1.blue,color2.blue,position); | |
| 35 | + | result.alpha := Interp256(color1.alpha,color2.alpha,position); | |
| 36 | + | end; | |
| 37 | + | ||
| 38 | + | function CreateWoodTexture(tx,ty: integer): TBGRABitmap; | |
| 39 | + | var | |
| 40 | + | colorOscillation, globalColorVariation: integer; | |
| 41 | + | p: PBGRAPixel; | |
| 42 | + | i: Integer; | |
| 43 | + | begin | |
| 44 | + | result := CreateCyclicPerlinNoiseMap(tx,ty,1.5,1.5,1,rfBestQuality); | |
| 45 | + | p := result.Data; | |
| 46 | + | for i := 0 to result.NbPixels-1 do | |
| 47 | + | begin | |
| 48 | + | colorOscillation := round(sqrt((sin(p^.red*Pi/16)+1)/2)*256); | |
| 49 | + | globalColorVariation := p^.red; | |
| 50 | + | p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation), | |
| 51 | + | Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation); | |
| 52 | + | inc(p); | |
| 53 | + | end; | |
| 54 | + | end; | |
| 55 | + | ||
| 56 | + | function CreateVerticalWoodTexture(tx, ty: integer): TBGRABitmap; | |
| 57 | + | var | |
| 58 | + | globalPos: single; | |
| 59 | + | colorOscillation, globalColorVariation: integer; | |
| 60 | + | p: PBGRAPixel; | |
| 61 | + | i: Integer; | |
| 62 | + | x,nbVertical: integer; | |
| 63 | + | begin | |
| 64 | + | result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1,rfBestQuality); | |
| 65 | + | p := result.Data; | |
| 66 | + | x := 0; | |
| 67 | + | nbVertical := tx div 128; | |
| 68 | + | if nbVertical = 0 then nbVertical := 1; | |
| 69 | + | for i := 0 to result.NbPixels-1 do | |
| 70 | + | begin | |
| 71 | + | globalPos := p^.red*Pi/32 + nbVertical*x*2*Pi/tx*8; | |
| 72 | + | colorOscillation := round(sqrt((sin(globalPos)+1)/2)*256); | |
| 73 | + | globalColorVariation := p^.red; //round(sin(globalPos/8)*128+128); | |
| 74 | + | p^:= Interp256( Interp256(BGRA(247,188,120),BGRA(255,218,170),colorOscillation), | |
| 75 | + | Interp256(BGRA(157,97,60),BGRA(202,145,112),colorOscillation), globalColorVariation); | |
| 76 | + | inc(p); | |
| 77 | + | inc(x); | |
| 78 | + | if x = tx then x := 0; | |
| 79 | + | end; | |
| 80 | + | end; | |
| 81 | + | ||
| 82 | + | function CreateGrassTexture(tx,ty: integer): TBGRABitmap; | |
| 83 | + | var | |
| 84 | + | p: PBGRAPixel; | |
| 85 | + | i: Integer; | |
| 86 | + | begin | |
| 87 | + | result := CreateCyclicPerlinNoiseMap(tx,ty,1,1,1,rfBestQuality); | |
| 88 | + | p := result.Data; | |
| 89 | + | for i := 0 to result.NbPixels-1 do | |
| 90 | + | begin | |
| 91 | + | p^ := Interp256( BGRA(0,128,0), BGRA(192,255,0), p^.red ); | |
| 92 | + | inc(p); | |
| 93 | + | end; | |
| 94 | + | end; | |
| 95 | + | ||
| 96 | + | end. | |
| 97 | + | ``` | |
| 98 | + | ||
| 99 | + | ## Holzwürfel auf dem Gras | |
| 100 | + | ||
| 101 | + | Hier ist eine Unit die eine Szene erzeugt mit einem Flecken Gras und darauf einem Würfel aus Holz: | |
| 102 | + | ||
| 103 | + | ``` pascal | |
| 104 | + | unit ex2; | |
| 105 | + | ||
| 106 | + | {$mode objfpc}{$H+} | |
| 107 | + | ||
| 108 | + | interface | |
| 109 | + | ||
| 110 | + | uses | |
| 111 | + | Classes, SysUtils, BGRAScene3D, BGRABitmap, BGRABitmapTypes; | |
| 112 | + | ||
| 113 | + | type | |
| 114 | + | { TExample2 } | |
| 115 | + | ||
| 116 | + | TExample2 = class(TBGRAScene3D) | |
| 117 | + | grass,wood,vWood: TBGRABitmap; | |
| 118 | + | ||
| 119 | + | constructor Create; | |
| 120 | + | procedure ApplyTexCoord(face: IBGRAFace3D; Times: integer = 2); | |
| 121 | + | procedure Render; override; | |
| 122 | + | destructor Destroy; override; | |
| 123 | + | end; | |
| 124 | + | ||
| 125 | + | implementation | |
| 126 | + | ||
| 127 | + | uses utexture; | |
| 128 | + | ||
| 129 | + | const texSize = 128; | |
| 130 | + | ||
| 131 | + | { TExample2 } | |
| 132 | + | ||
| 133 | + | constructor TExample2.Create; | |
| 134 | + | var | |
| 135 | + | base,v: array of IBGRAVertex3D; | |
| 136 | + | box : IBGRAObject3D; | |
| 137 | + | begin | |
| 138 | + | inherited Create; | |
| 139 | + | ||
| 140 | + | //erzeugt die Texturen | |
| 141 | + | grass := CreateGrassTexture(texSize,texSize); | |
| 142 | + | vWood := CreateVerticalWoodTexture(texSize,texSize); | |
| 143 | + | wood := CreateWoodTexture(texSize,texSize); | |
| 144 | + | ||
| 145 | + | //erzeugt den Boden | |
| 146 | + | with CreateObject(grass) do | |
| 147 | + | begin | |
| 148 | + | base := MainPart.Add([-50,20,-50, -50,20,50, 50,20,50, 50,20,-50]); | |
| 149 | + | ApplyTexCoord(AddFace(base),4); | |
| 150 | + | end; | |
| 151 | + | ||
| 152 | + | //erzeugt die Holzkiste | |
| 153 | + | box := CreateObject(vWood); | |
| 154 | + | with box do | |
| 155 | + | begin | |
| 156 | + | v := MainPart.Add([-1,-1,-1, 1,-1,-1, 1,1,-1, -1,1,-1, | |
| 157 | + | -1,-1,+1, 1,-1,+1, 1,1,+1, -1,1,+1]); | |
| 158 | + | ||
| 159 | + | ApplyTexCoord(AddFace([v[0],v[1],v[2],v[3]])); | |
| 160 | + | ApplyTexCoord(AddFace([v[4],v[5],v[1],v[0]],wood)); | |
| 161 | + | ApplyTexCoord(AddFace([v[7],v[6],v[5],v[4]])); | |
| 162 | + | ApplyTexCoord(AddFace([v[3],v[2],v[6],v[7]],wood)); | |
| 163 | + | ApplyTexCoord(AddFace([v[1],v[5],v[6],v[2]])); | |
| 164 | + | ApplyTexCoord(AddFace([v[4],v[0],v[3],v[7]])); | |
| 165 | + | ||
| 166 | + | MainPart.Scale(20); | |
| 167 | + | end; | |
| 168 | + | //RemoveObject(box); | |
| 169 | + | ||
| 170 | + | ViewPoint := Point3D(-40,-40,-100); | |
| 171 | + | end; | |
| 172 | + | ||
| 173 | + | procedure TExample2.ApplyTexCoord(face: IBGRAFace3D; Times: integer); | |
| 174 | + | begin | |
| 175 | + | with face do | |
| 176 | + | begin | |
| 177 | + | TexCoord[0] := PointF(0,0); | |
| 178 | + | TexCoord[1] := PointF(texSize*Times-1,0); | |
| 179 | + | TexCoord[2] := PointF(texSize*Times-1,texSize*Times-1); | |
| 180 | + | TexCoord[3] := PointF(0,texSize*Times-1); | |
| 181 | + | end; | |
| 182 | + | end; | |
| 183 | + | ||
| 184 | + | procedure TExample2.Render; | |
| 185 | + | begin | |
| 186 | + | inherited Render; | |
| 187 | + | end; | |
| 188 | + | ||
| 189 | + | destructor TExample2.Destroy; | |
| 190 | + | begin | |
| 191 | + | grass.free; | |
| 192 | + | wood.free; | |
| 193 | + | vWood.free; | |
| 194 | + | inherited Destroy; | |
| 195 | + | end; | |
| 196 | + | ||
| 197 | + | end. | |
| 198 | + | ``` | |
| 199 | + | ||
| 200 | + | Zuerst werden die benötigten Texturen erzeugt. Der Grasflecken ist ein Objekt mit Grastextur, festgelegt durch 4 Kanten. Die Textur ist als Parameter der Funktion "CreateObject" festgelegt. "AddFace" gibt ein IBGRAFace3D-Objekt zurück, das an die benutzerdefinierte Prozedur "ApplyTexCoord" weitergegeben wird. Diese Prozedur setzt die Eigenschaft "TexCoord" einen jeden Kante der Fläche. Diese Koordinaten sind pixelzentrierte Fließkommakoordinaten. | |
| 201 | + | ||
| 202 | + | Die hölzerne Kiste wird als Objekt mit vertikaler Holztextur erzeugt. Die Kanten definieren einen Würfel mit Unit-Koordinaten. Dieser wird später skaliert. Beim Erzeugen der Grund- und Deckfläche wenden wir eine andere Textur an, nämlich eine dazu senkrechte Holztextur. | |
| 203 | + | ||
| 204 | + | Zuletzt legen wir die Sichtbarkeit fest. Die soll ein bisschen von der Seite erfolgen. Der Standardwert ist (0,0,-100). Auf diese Weise hat die Szene etwas Perspektive. | |
| 205 | + | ||
| 206 | + | <figure> | |
| 207 | + | <img src="BGRATutorial16a.png" title="BGRATutorial16a.png" /> | |
| 208 | + | <figcaption>BGRATutorial16a.png</figcaption> | |
| 209 | + | </figure> | |
| 210 | + | ||
| 211 | + | ### Beleuchtung und Normalen | |
| 212 | + | ||
| 213 | + | Wir fügen einfach etwas Licht hinzu: | |
| 214 | + | ||
| 215 | + | ``` pascal | |
| 216 | + | LightingNormal:= lnFace; | |
| 217 | + | ||
| 218 | + | AmbiantLightness := 0.25; | |
| 219 | + | with CreateObject do | |
| 220 | + | begin | |
| 221 | + | AddPointLight(MainPart.Add(-100,-80,0),140,0.5); | |
| 222 | + | end; | |
| 223 | + | ``` | |
| 224 | + | ||
| 225 | + | Hier wird die Helligkeit genau so wie im letzten Tutorial verwendet. Aber die Lichtquelle ist punktförmig. Um eine Kante festzulegen brauchen wir ein Objekt, das diese beinhaltet. Es ist möglich, später das Licht zu verschieben. Je weiter ein Objekt vom Licht entfernt ist, desto dunkler ist es. Der Parameter der optimalen Distanz gibt die Distanz an, die Lichtintensität steht im nächsten Parameter. Das bedeutet, wenn ein Objekt in einer Distanz von 140 ist, dann ist die Helligkeit 0.5. | |
| 226 | + | ||
| 227 | + | Beachten Sie: Wir haben LightingNormal zu lnFace festgelegt. Dies ergibt, dass das Licht so berechnet wird, als wären die Seitenflächen flach. Die Beleutung berücksichtigt keine Abrundungen. Die könnte in anderen Fällen nützlich sein, aber nicht hier. | |
| 228 | + | ||
| 229 | + | <figure> | |
| 230 | + | <img src="BGRATutorial16b.png" title="BGRATutorial16b.png" /> | |
| 231 | + | <figcaption>BGRATutorial16b.png</figcaption> | |
| 232 | + | </figure> | |
| 233 | + | ||
| 234 | + | [[BGRABitmap tutorial 15/de|Voriges Tutorial (3D)]] | |
| 235 | + | ||
| 236 | + | Seite übersetzt durch: --billyraybones 12:06, 23 October 2011 (CEST) | |
| 237 | + | ||
| 238 | + | --- | |
| 239 | + | *From the Free Pascal wiki, page "BGRABitmap tutorial 16/de", 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).* |
