BlitzBasic-Community-Tutorial/ Einführung in Blitz3D
Nachfolgend werden die wichtigsten Unterschiede von B3D im gegensatz zu B2D erläutert.
Graphics3d, RenderWorld
[Bearbeiten]Bei BlitzBasic stand am Anfang immer Graphics und in einer Mainloop immer Cls und Flip. Bei Blitz3d kommen noch UpdateWorld und RenderWorld hinzu, das Cls kann weggelassen werden. Der 3d-Modus wird durch Graphics3d initialisiert. Seine anderen Parameter sind wie schon von Graphics bekannt.
Graphics3D 800,600,16,2 SetBuffer BackBuffer() Repeat ;Animationen updaten UpdateWorld ;Szene rendern RenderWorld Flip Until KeyHit(1) End
Updateworld aktuallisiert Kollisionen und Animationen, die einem Blitz vollständig berechnet, Renderworld zeichnet die gesamte 3dSzene. Man zeichnet nicht mehr manuell einzelne Bilder, sondern RenderWorld zeichnet alle vorher definierten Entities.
Entities?!
[Bearbeiten]Eine der größten Neuheiten von Blitz3d gegenüber BlitzBasic ist das Entitysystem. Entity ist ein englisches Wort für Ding, Dasein, Gebilde, Einheit, Objekt. Die gesamte 3dWelt besteht aus Entities. Egal ob Boden, Figur oder Sonne, jedes Objekt ist eine Entity. Entites haben alle dieselben Grundeigenschaften, wie Position, Drehung, Größe und Bezugssystem.
Anders als in BlitzBasic, wo man Bilder immer wieder von neuem Zeichnen muss, bleiben einmal erstellte 3d-Objekte solange bestehen, bis man sie löscht. Das ist nach BlitzBasic vielleicht etwas gewöhnungsbedürftig, aber schlussendlich doch recht logisch: Man baut einmal eine Welt und manipuliert sie dann, anstatt sie jedes Frame von vorne aufzubauen.
Kamera
[Bearbeiten]Wie auch im Film braucht man für eine ordentliche Szene nicht nur eine Szene, sondern vor allen Dingen eine Kamera. Ohne Kamera kein Film. Ohne Kamera auch kein PC-Spiel. Kameras sind Entities, die angeben, wo und wie man auf die Welt schaut. Erstellt werden sie mit CreateCamera() vor der Hauptschleife. Der Befehl liefert das Handle der Kamera zurück. Das ist eine Zahl, mit der man wieder auf das Entity zugreifen kann. Man behandelt die Kamera dann wie alle anderen Entities. Zur Entitybehandlung kommen wir gleich.
Graphics3d 800,600,16,2 SetBuffer Backbuffer() camera = CreateCamera() Repeat Cls ;Aktuallisieren UpdateWorld Renderworld Flip Until KeyHit(1) End
Nichts zu sehen? Tja, was auch?
Würfel, Kugeln, Zylinder, Kegel
[Bearbeiten]In BlitzBasic kann man zum Testen von 2d-Dingen Grundformen mit Oval und Rect Grundformen zeichnen (in Blitz3D kann man das natürlich auch, man muss die Befehle aber nach RenderWorld und vor Flip setzen). Auch in Blitz3d gibt es solche Grundformen, beziehungsweise natürlich -körper: die aus Mathe und vielen 3d-Programmen bekannten Grundfiguren Würfel, Kugeln, Zylinder und Kegel. Man nennt sie Primitves. Und die brauchen wir jetzt, damit wir etwas zum Anschauen und Testen haben.
Würfel werden mit CreateCube() erstellt. Kugeln mit CreateSphere(), Zylinder mit CreateCylinder(), Kegel mit CreateCone().
Mehr von den Entitäten
[Bearbeiten]Jippy, endlich kann es losgehen! Zeit für unsere erste Szene. Es werden ein paar Primitives erstellt und vor der Kamera angeordnet.
Graphics3D 800,600,32,2 SetBuffer BackBuffer() camera = CreateCamera() cube = CreateCube() PositionEntity cube,-2,0,5 sphere = CreateSphere() PositionEntity sphere,0,2,5 cylinder = CreateCylinder() PositionEntity cylinder,1,5,0,3 cone = CreateCone() PositionEntity cone,0,-2,5 Repeat Cls RenderWorld Flip Until KeyHit(1) End
Zum positionieren der Entities nutzt man PositionEntity. Der erste Parameter gibt das zu positionierende Entity an, die drei Zahlen danach geben die X-, Y- und Z-Koordinaten an.
X,Y und Z
[Bearbeiten]Koordinaten werden in 3d nicht ganz so angegeben wie in 2d. Der auffälligste Unterschied ist wohl, dass es nicht mehr nur X und Y, sondern auch noch einen dritten Bestandteil, Z, gibt. Z steht für die Tiefe.
Der Urprung der Welt liegt an 0,0,0. Objekte werden normalerweise am Ursprung erstellt und zeigen entlang der Z-Achse. So auch die Kamera. 0,0,0 ist bei einer unbewegten Kamera immer genau der Mittelpunkt des Bildschirms auf der Kameralinse.
Schauen wir uns einmal das letzte Beispiel an. Der Würfel/Cube wird mit PositionEntity an -2,0,5 positioniert. -2 als X-Wert bedeutet, dass der Würfel zwei Einheiten links von der Bildschirmmitte liegt. Ist er positiv, so liegt das Objekt weiter rechts. Der Z-Wert von 5 verschiebt das Objekt nach hinten. Wenn man ihn weiter erhöht, wird das Objekt nach hinten verschoben, also kleiner und bewegt sich auf den Fluchtpunkt zu.
Mit dem Y-Wert verhält es sich genau wie in Mathe: Je größer der Wert, desto weiter oben der Punkt. Also nicht mehr wie im 2d-Modus umgekehrt.
Licht
[Bearbeiten]Natürlich bietet Blitz3D weit mehr als nur den Umgang mit Entities. Man kann z.B. eine Lichtquelle erstellen und diese frei im Raum positionieren. Dies erreicht man mit dem Befehl CreateLight(). CreateLight() erzeugt eine Lichtquelle, die fast genauso wie alle anderen Entities behandelt wird: Man kann sie genau wie alle anderen Entities drehen, verschieben und positionieren.
light = CreateLight(1)
Was sucht denn die 1 da? Fragt sich jetzt der ein oder andere. Dem Befehl CreateLight() kann eine Zahl von 1-3 zugewiesen werden.
Createlight(1) ;gerichtetes Licht Createlight(2) ;Punkt-Licht Createlight(3) ;Spot-Licht
Damit kann man jetzt mal ne Runde rumspielen!
Einfach, wie vorher beschrieben, ein Entity hinzaubern und dann mal kucken was die Lichter machen. Dazu noch ein Quelltext
Graphics3D 640,480 camera = CreateCamera() MoveEntity camera,0,0,-3 dings = CreateCube() licht = CreateLight(1) ;Verändere den Wert in den Klammern (1,2 oder 3?) MoveEntity licht,5,0,0 PointEntity licht,dings ;Wir richten unser "gerichtetes Licht" auf den Würfel While Not KeyDown(1) RenderWorld:Flip Wend End
Zusätze zum Licht
Mit unserem "Licht=Createlight(x)" können wir noch ne Menge anstellen!
Zum Beispiel: Zusätzliche Befehle nutzen um Reichweite und Scherze zu modifizieren.
Zur Reichweite
LightRange licht,reichweite#
heißt das gute Stück und damit können wir unserem licht eine neue Reichweite zuweisen. Normalerweise hat jedes Licht, welches mit CreateLight() erstellt wurde, eine Reichweite von 1000.0 Hier sollte wieder jeder den Befehl in den Code einfügen und damit ein wenig rumspielen. Werte ändern und kucken was passiert!
LightColor licht,rot,grün,blau
Macht genau dass, was sich jetzt die meisten denken. Es ändert einfach die Farbe des Lichts.
Und was macht
LightConeAngles licht,innerer-winkel,äußerer-winkel
???? Es verändert den Winkel des Lichtkegels eines Spotlights.
Dass heißt: Wir brauchen ein Spotlight! Also:
Graphics3D 1024,768,32,1 camera=CreateCamera() SetBuffer BackBuffer() dingns = CreateCube() licht=CreateLight(3) ;unser "Spot Light" LightConeAngles licht,10,10 ;dem weisen wir mal ein paar Winkel zu PositionEntity dingns,0,0,10 Repeat Cls ;Hier werden die Pfeiltasten abgefragt If KeyDown(208) pitch=pitch+1 ;oben If KeyDown(200) pitch=pitch-1 ;unten If KeyDown(203) yaw=yaw+1 ;links If KeyDown(205) yaw=yaw-1 ;rechts RotateEntity dings,pitch,yaw,0 ;Ein neuer Befehl, welcher unseren Würfel dreht UpdateWorld RenderWorld Flip Until KeyHit(1) End
Hier ist der Befehl RotateEntity dinges,Pitch,Yaw,Roll. Dieser dreht, selbstverständlich, ein Objekt in unserer kleinen 3D Welt.
- Pitch ist die Drehung auf der X-Achse des Objekts
- Yaw ist die Drehung auf der Y-Achse des Objekts
- und, natürlich, ist der letzte Wert Roll die Drehung auf der Z-Achse des Objekts
Hierbei ist zu beachten. Wenn ich mit Pitch den Würfel Dingens auf seiner eigenen X-Achse drehe, drehen sich die anderen Achsen von Dingens! Dadurch ist Y und Z Woanders. Hier gilt erneut! Rumspielen. Und sich vielleicht mal eine Zeichnung zum Verständnis malen.
Noch mehr zum Licht
Wir sind jetzt also fähig einen klobigen Würfel in die Welt zu setzen. Diesen mit einigen Lichttypen zu beschmeißen und ihn zu drehen. Nicht schlecht! Aber... Es gibt noch viel mehr!
Also, zur Sache.
EntityFX dingens,Zahl
Ist der neue, mächtige Befehl, den es zu meistern gilt! Er gibt einem Objekt einen Effekt. Welchen, entscheidet die Zahl!
- 0 - nichts(default)
- 1 - volle Helligkeit, oder strahlend
- 2 - Vertex-Beleuchtung ;Also, jedes Polygon bekommt einen Farbwert
- 4 - Flat Shading ;Also, jeder Pixel eines Polygons bekommt einen Farbwert, jedoch hat jedes Polygon trotzdem nur eine Beleuchtungsstufe
- 8 - Nebeleffekt deaktivieren ;wird erst nötig, wenn wir wissen, was denn ein Nebeleffekt ist
- 16 - Backface Culling deaktivieren ;Backface Culling ist eine Technology, bei der alle nicht sichtbaren Polygone entfernt werden
- 32 - Vertex-Alpha aktivieren ;ein großes Thema, welches ich an dieser Stelle mal auslasse
Die Effekte können sogar kombiniert werden. Dazu rechnen wir die Zahlen der gewünschten Effekte zusammen (Also, z.B. 1+2=3) und schreiben dass Ergebnis rein.
EntityFX dingens,3
Mal wieder gilt, in den Code einfügen und damit rumspielen. 8,16 und 32 kann dabei ausgelassen werden. Damit beschäftigen wir uns noch früh genug.
Wir werten mal ein wenig zusammen aus:
Wenn unser Würfel den Effekt 1 hat, strahlt dieser. Dass bedeutet, wir sehen unser Licht nicht mehr, da dingens ja schon hell ist. Also ist die 1 in unserem Licht-Tutorial unnötig.
Bei Effekt 2 kommt eine sehr beknackte Lichtberechnung raus. Vertex-Licht kennt vielleicht der ein oder andere noch von alten Games. Dort gab es, zumeist, den Umschalter Vertex nutzen ja/nein. Damit will ich sagen, diese Art der Lichtberechnung ist sehr alt. Pre 2000.
Bei Effekt 4 hat jede Seite des Würfels ein Lichtwert? Leider ja.
Alle anderen Effekte brauchen wir nicht. Und was passiert bei dem kombinierten Effekt 2+4? Richtig, sieht auch schäbig aus. Wir nutzen erstmal Effekt 2.
LightMesh
LightMesh mesh,rot,grün,blau,[reichweite,licht_x,licht_y,licht_z]
Ein neuer Befehl! Dieser produziert ein "fake" Licht auf jedem Objekt. Voraussetzung dafür ist der Befehl EntityFX dings,2. Wenn wir jetzt unser Spotlight licht wegnehmen, neben unseren Würfel einen Würfel packen und den 1. mit Lightmesh behandeln, dann... Hier mal die aktualisierte Edition unseres Codes:
Graphics3D 1024,768,32,1 camera=CreateCamera() SetBuffer BackBuffer() blub=CreateCube() dings=CreateCube() EntityTexture dings,tex EntityFX blub,2 EntityFX dings,2 ;Den Effekt müssen wir vor LightMesh einbauen LightMesh dings,200,200,0 ;Wie machen dings mal gelblich PositionEntity dings,5,0,10 ;wir richten beide, nebeneinander auf der x Achse an PositionEntity blub,-5,0,10 Repeat ;und hier beginnt wieder die bekannte Hauptschleife Cls
If KeyDown(208) pitch=pitch+1 If KeyDown(200) pitch=pitch-1 If KeyDown(203) yaw=yaw+1 If KeyDown(205) yaw=yaw-1
RotateEntity blub,pitch,yaw,0 ,Mit dem Unterschied, dass blub sich dreht. UpdateWorld RenderWorld Flip Until KeyHit(1) End
Klappt nicht so ganz, ne? LightMesh setzt auch keine echte Lichtquelle ein. Sondern belichtet exakt ein Objekt mit den Werten.
AmbientLight
Übersetzt: Umgebungs Licht. Und genau darum handelt es sich auch! Dieser Befehl setzt eine Art "Sonne" ein. Ums genau zu nehmen, kann damit die Welt, unabhängig von allen anderen Lampen, erhellt werden.
Setzen wir dies in unseren Code mal ein.
AmbientLight rot,grün,blau
Diese Zeile kommt vor die Hauptschleife. Alle anderen Lichtquellen, sowie LightMesh kommt weg.
Tatsache ist, dieses Umgebungslicht war schon immer da. Per BB3D Standard Einstellung gibt es immer ein Umgebungslicht mit den Werten 127,127,127. Hintergrund dieser Standard Einstellung ist, dass junge Entwickler überhaupt was sehen.
Dadurch können wir also auch die Welt schwärzen und alles blau färben.
Kreation einer logischen Lichtquelle
Ich habe es mir mal erlaubt, unsere Lichtquelle in einen Würfel zu packen und sie auf den anderen Würfel zu richten. Dadurch entsteht eine halbwegs logische Lichtquelle.
Jedoch ist dabei noch vieles hinzuzufügen.
- Der Würfel muss leuchten
- Der Würfel muss mehr nach Glas aussehen.
das Leuchten erreichen wir mit LightMesh (siehe oben).
Da greife ich mal dem Thema Textur vor und lade mit den Befehl tex=LoadTexture("grau.png") ein 258*258 großes Bild, welches einfach nur grau ist. Dieses lege ich mit dem Befehl EntityTexture würfel,tex auf meinen Würfel. Dadurch ist dieser komplett grau. Dank LightMesh sieht er was aus wie ein Leuchtender Würfel. Und jetzt mach ich daraus ne Kugel und... es entsteht eine halbwegs logische Lichtquelle.
Texturen
[Bearbeiten]LoadTexture
Ist der erste und wichtigste Befehl. Denn, wenn wir keine Textur laden, können wir diese auch auf kein Objekt malen, ne?
Es funktioniert folgender Weise:
texture=LoadTexture(Pfad$,[Zahl])
Ich mache es meistens so:
Den Code in einen Ordner speichern und alle Daten, welche ich laden möchte, dort reinpacken.
;Dadurch ändert sich Pfad einfach in Dateiname textur=Loadtexture("Dateiname.png",[Zahl])
Die Textur ist so etwas Ähnliches wie ein Bild in der 2D Umgebung. Wir müssen es erstmal irgendwo zeichnen.
Der Unterschied ist, bei einer Textur, muss diese auf ein Objekt mit mindestens 1 Polygon gezeichnet werden. Sozusagen, nicht auf die Kamera und auch nicht auf das Licht.
Dafür gibt es diesen Befehl:
EntityTexture dings,textur
Aus dem Abschnitt Licht haben wir noch einen Code:
Graphics3D 1024,768,32,1 camera=CreateCamera() SetBuffer BackBuffer() blub=CreateCube() dings=CreateCube() tex=LoadTexture("brick-01.png") ;wir laden die Textur EntityTexture dings,tex ;Wir packen sie auf unseren Würfel "dings" EntityFX dings,2 EntityFX blub,2 PositionEntity dings,5,0,10 PositionEntity blub,-5,0,10 AmbientLight 255,255,255 ;Für gute Sichtverhältnisse sorgt ein Umgebungslicht Repeat ,Die bekannte Schleife Cls If KeyDown(208) pitch=pitch+1 If KeyDown(200) pitch=pitch-1 If KeyDown(203) yaw=yaw+1 If KeyDown(205) yaw=yaw-1 RotateEntity blub,pitch,yaw,0 UpdateWorld RenderWorld Flip Until KeyHit(1) End
Bei LoadTexture gibt es ja noch die [Zahl]!
Dazu eine Übersicht:
- 1 - Farbe (Standard)
- 2 - Mit Alpha-Information
- 4 - Mit 0,0,0 Maske ;also, alle Bereiche einer Textur, welche den Farbwert 0,0,0 schneidet BB3D weg
- 8 - Mipmapping ;bei größeren Entfernungen zum Objekt wird die Textur in einer geringeren Qualität dargestellt
- 16 - Klemme U ;dazu kommen wir noch
- 32 - Klemme V ;dazu kommen wir noch ;)
- 64 - Reflections Textur ;Umgebung-mapping, für den shiny, metall-look
- 128 - in meiner Version von BB3D nicht benutzt ;als definition cubic-enviroment-mapping für einen effizenteren shiny, metall-look
- 256 - Speichere die Textur in den vRAM ;speichert die Textur zur schnelleren Berechnung in der Arbeitsspeicher der Grafikkarte
- 512 - Erzwingt die Nutzung einer hochauflösenden Textur in einer 16 bit Grafikeinstellung
Wir sehen schon, LoadTexture ist ein äußerst mächtiger Befehl. Aber, was zum Teufel bedeutet bitte "Alpha"?
Alpha
Ein Bild kann eine zusätzliche Information, neben seinen normalen Farben speichern. Die Alpha Information. Diese beinhaltet, welche Bereiche des Bildes wie stark ausgeblendet werden. dadurch wird ein Farbverlauf von Farbe r,g,b zu farblos möglich.
Dieses muss mit einem Bildbearbeitungsprogramm geschehen, welches besser als MS Paint ist.
BB3D kann diese Information lesen. Durch den Befehl LoadTexture("textur.bmp",2) Wird die Alhpa-Information verarbeitet.
Multi-Textur
Wir haben bis jetzt eine Textur geladen und diese auf unseren Würfel gepackt. Jetzt Soll noch eine Textur darüber.
Dazu gibt es mehrere Möglichkeiten:
- LoadTexture("tex1.bmp",2) ;Also, mit Alpha Info
- LoadTexture("tex1.bmp",4) ;Also, alles was ganz schwarz ist, bitte weglassen
tex1=LoadTexture("block-01.png") ;Hier laden wir sogar 4 Texturen tex2=LoadTexture("block-02.png",2) tex3=LoadTexture("block-03.png",4) tex4=LoadTexture("block-04.png",4) EntityTexture dings,tex1 ;Hier zeichnen wir nacheinander tex1 und tex2 auf den Würfel dings EntityTexture dings,tex2 ;Zuerst tex1, da diese voll Farbig ist, danach tex2, da diese Alpha Informationen enthält
Dadurch wird tex2 und tex1 zusammengemischt. Da aus tex2 einiges aus geschnitten wird, ist in den farblosen Bereichen tex1 zu sehen. In allen anderen Bereichen, werden die Texturen gemischt. Dies kann man jetzt mit sehr vielen Texturen machen.
Und genau dass ist MultiTexturing. Einfach, mehr als eine Textur auf einem 3D Objekt.
Und, wenn BB3D weiß, wie dies geschehen soll, kann das Ergebnis richtig gut aussehen!
An dieser Stelle möchte ich erneut darauf hinweisen, dass ein jeder Leser jetzt mit den vielen neuen befehlen arbeiten sollte.
Terrain
Wir können also kleine 3D Objekte Erstellen und diese mit einer Textur bemalen. Wir wissen, dass BB3D Alpha Informationen verarbeiten kann, wenn wir diese unseresn Bildern mit auf den Weg gegeben haben.
Doch, was ist unsere 3D Welt ohne ein Terrain?
Wie erstellen wir ein Terrain? und was ist dass schon wieder?
Das Terrain ist der Untere Boden unserer Welt. Auf der steht alles. Also, wollen wir mal ein Terrain selbst erstellen:
terrain=CreateTerrain([größe])
Dadurch erstellen wir ein Terrain. Es erstreckt sich Standard mäßig von 0,0,0 (Der Ursprung des KoordinatenSystems) zu größe,größe,1. Das bedeutet, wir bekommen eine Fläche, welche den Boden darstellt.
Mal wieder ein kleiner Code zum kucken. Wichtig! Schmiert bitte irgendeine Textur auf das Terrain!
Graphics3D 1024,768,32,1 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,1,0 lichtt=CreateLight() MoveEntity licht,0,50,0 RotateEntity licht,90,0,0 ; Create terrain terrain=CreateTerrain(128) ; Texture terrain grass_tex=LoadTexture( "grass.bmp" ) EntityTexture terrain,grass_tex While Not KeyDown( 1 ) If KeyDown( 205 )=True Then TurnEntity camera,0,-1,0 If KeyDown( 203 )=True Then TurnEntity camera,0,1,0 If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.5 If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.5 RenderWorld Text 0,0,"Benutze die Pfeiltasten um über das Terrain zu fliegen." Flip Wend End
Ihr seht, wir haben jetzt eine gewissen Fläche Spielplatz. Jedoch, ohne jegliche Höhe oder Tiefe! Wenn wir ein Terrain mit CreateTerrain erstellen ist dieses automatisch Flach.
Dieses Terrain kann man leider nur sehr schwer mit BB3D bearbeiten. Es ist zwar möglich, jedoch viel zu Umständlich für uns.
Der einfache Weg ist ein Terrain zu laden! Nur, wo bekommen wir dass den her?
Wir müssen erneut ein Bild malen. Nur, dieses Bild muss aus Farbverläufen zwischen schwarz und weiß bestehen und groß sein. Die Größe des Bildes entscheidet darüber, wie groß unser Terrain wird. Je weißer das Bild, desto höher wird der entsprechende Punkt auf der Z-Achse. je schwarzer der Punkt, desto tiefer liegt er auf der Z-Achse.
Nach diesen Kriterien müssen wir jetzt also ein Bild zusammen pfriemeln.
Wenn du jetzt gerade keine Lust hast ein Bild zu malen. dann schau doch mal in deinen BB3D Ordner unter Samples nach. Dort gibt es einige hervorragende Bilder.
Diese Laden wir mit
terrain=LoadTerrain("terrain.bmp")
Dieser Befehl liest die Datei "terrain.bmp", verarbeitet diese zu einem Terrain und erstellt es am Ursprung.
Diesen kann man einfach mit CreateTerrain ersetzten und erneut rumfliegen.
"Das Terrain ist noch immer flach." Mag man jetzt schreien. Stimmt jedoch nicht ganz. BB3D hat uns ein fast flaches Terrain hingezaubert. Denn, BB3D macht es manchmal viel zu groß.
Wenn wir diesem entgehen wollen, brauchen wir
ScaleEntity terrain,x,y,z
Dieser Befehl verändert die größe eines Objekts.
Wir versuchen es also und setzen ScaleEntity terrain,2,2,2 ein. Der Wert 2,2,2 sagt aus, dass das Objekt terrain in jede Richtung doppelt so groß ist. Entsprechend kannst du jetzt die Werte einstellen, sodass dein Terrain gut aussieht.
Wenn dein Terrain zu hoch ist, oder zu kantig, solltest du versuchen, ein wesentlich geschmeidigeres Bild zu malen. Es muss ein guter Farbverlauf von schwarz zu weiß vorhanden sein.
(psst. Dazu, sollten man vielleicht auch noch ne Menge Licht in die Szene bringen.)
Mal ein kleiner Quellcode, wie es jetzt bei mir im guten blah.bb aussieht:
Graphics3D 1024,768,32,1 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,100,0 light=CreateLight() MoveEntity light,0,0,50 RotateEntity light,22.5,0,0 ; Create terrain terrain=LoadTerrain("hmap_1024.bmp") ScaleEntity terrain,1,20,1 ;der Faktor 20 auf der y-Achse, damit die Berge auch Berge sind EntityFX terrain,1 ;Da die kleine Leuchte von oben nix bringt ; Texture terrain grass_tex=LoadTexture( "brick-01.png" ) EntityTexture terrain,grass_tex While Not KeyDown( 1 ) If KeyDown( 205 ) TurnEntity camera,0,-1,0 If KeyDown( 203 ) TurnEntity camera,0,1,0 If KeyDown( 208 ) MoveEntity camera,0,0,-1 If KeyDown( 200 ) MoveEntity camera,0,0,1 If KeyDown(44) MoveEntity camera,0,-1,0 ;Y um nach unter zu fliegen If KeyDown(30) MoveEntity camera,0,1,0 ;a um nach oben zu fliegen RenderWorld Text 0,0,"Benutze die Pfeiltasten und A/Y zum Bewegen." Flip Wend End
Wenn du jetzt diesen Code hast und durch das Terrain fliegt fällt dir auf, dass sich das Terrain beim vorbeifliegen verändert. Dies ist hängt damit zusammen, dass BB3D ein Terrain automatisch mit einer sehr geringen Polygonen Zahl darstellt. Es verändert, da mehr Polygone hinzugefügt werden, je näher die Kamera ist.
Wir können allerdings auch mit dem Befehl
TerrainDetail terrain,detail_level,vertex_morph
Unser Terrain besser darstellen.
Also, fügen wir, nach dem Laden des Terrain und vor der Haupt-Schleife, diesen Befehl ein. Eine typische Detailstufe ist 2000. Es wird korrekt angezeigt ohne Endlos Resourcen zu nutzen.
Der Zusatz vertex_morph kann nur wahr oder falsch sein. Er sagt einfach aus, ob den Morph genutzt wird. Ich empfehle dies Anzuschalten. Vertex Morph ist einfach eine verbesserte Methode der Verformung eines Polygon-Objekts.
Dadurch haben wir jetzt ein Terrain, welches, zumindest hoffe ich das, relativ groß und bergig ist. Jedoch, wird es wohl nicht super gut aussehen wegen der Textur.
Terrain und Textur
Ein äußerst großes Thema, welches wir hier betreten.
Wenn wir eine Textur laden und diese einfach mit EntityTexture auf unser Terrain malen, wird die Textur von BB3D so oft wiederholt, bis es über das gesamte Terrain verteilt wird.
Beispielsweise:
Unser Terrain ist 640,640 groß. Die Textur ist 80,80 groß. Also, wird die Textur 640:80=8 mal auf das Terrain gepackt.
Mein Terrain, ist tatsächlich 1024 groß und die Textur ist 256. Also wird meine Textur 4 mal auf das Terrain gemalt. Da Terrain aber zusätzlich noch nach oben geht, wird die Textur in der Praxis wesentlich öfter auf das Terrain gemalt.
Wie können wir etwas tun?
Wir können die Textur an die Größe des Terrains anpassen.
ScaleTexture textur,TerrainSize(terrain),TerrainSize(terrain)
Zwei neue Befehle: ScaleTexture vergrößert eine Textur um die Faktoren. TerrainSize(terrain) gibt die Größe unseres Terrains aus. Dadurch wird die Textur auf unser Terrain angepasst, solange dieses auf der x und z Achse gleichgroß ist.
Ansonsten könnten da wilde Experimente entstehen.
Zum vollständigen Code:
Graphics3D 1024,768,32,1 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,100,0 light=CreateLight() MoveEntity light,0,0,50 RotateEntity light,22.5,0,0 ; Create terrain terrain=LoadTerrain("hmap_1024.bmp") ScaleEntity terrain,1,20,1 EntityFX terrain,1 TerrainDetail terrain,4000,True ; Texture terrain grass_tex=LoadTexture( "lmap_256.bmp" ) EntityTexture terrain,grass_tex ScaleTexture grass_tex,TerrainSize(terrain),TerrainSize(terrain) While Not KeyDown( 1 ) If KeyDown( 205 ) TurnEntity camera,0,-1,0 If KeyDown( 203 ) TurnEntity camera,0,1,0 If KeyDown( 208 ) MoveEntity camera,0,0,-1 If KeyDown( 200 ) MoveEntity camera,0,0,1 If KeyDown(44) MoveEntity camera,0,-1,0 If KeyDown(30) MoveEntity camera,0,1,0 RenderWorld Text 0,0,"Benutze die Pfeiltasten und A/Y zum Bewegen." Flip Wend End
"Aus der Entfernung kann es sich sehen lassen, doch wenn ich nah ran fliege, bäh!" Wir haben jetzt die Grafik von Outcast erreicht! Juhu!
Jetzt, kann man einerseits eine Textur mal die einfach so passt, wobei dass sehr schwer zu berechnen ist, wie groß die Textur sein muss. Oder, wir tricksen ein wenig rum.
Der Befehl EntityTexture ist sehr mächtig
EntityTexture terrain,texture,0,0
Was sollen jetzt die beiden Nullen da? Ganz einfach. Die erste Null steht für den Frame innerhalb der Textur. Da es nur 1 Frame gibt, bleibt dass bei einer null, damit BB dies ignoriert. Die zweite null ist eine Index Zahl. Dadurch wird dem Terrain die Textur zugewiesen und bekommet die Identifikationsnummer 0. Dadurch wird sie direkt ansprechbar.
Das ganze machen wir jetzt mit einer 2. Textu
EntityTexture terrain,texture2,0,1
Jetzt haben wir dem Terrain 2 Texturen zugewiesen. Nummer 0 und 1.
Jetzt füge man dies in den Code ein. Also, direkt nach dem Laden der 1. Textur, laden wir eine 2. Diese werden dann beide mit EntityTexture terrain,textur,0,x dem Terrain zugewiesen und von BB rauf gemalt.
Die Frage ist nun, warum sieht dass ganze denn jetzt besser aus? 1. Weil BB3D gut ist. 2. Weil die beiden Texturen gemischt werden, denn 1.
Natürlich kommt es darauf an welche Texturen du da jetzt rauf gemalt hast. Einmal Holz und Steine macht sich ein wenig komisch auf einem Terrain. Grüne und braune Fabren in der 1. Textur, welche über das gesamte Terrain gezogen wird, und ein grauer Unterton kann sich schonwieder sehen lassen.
Soviel zum Terrain
LoadMesh
[Bearbeiten]- Hier fehlen noch Inhalte! Bitte ergänzen!