Perspektivenkorrektur für Gloweffekt
Übersicht

KrischanBetreff: Perspektivenkorrektur für Gloweffekt |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich bastel gerade an einem Gloweffekt für Planeten. Ich habe dazu auch schon alle möglichen Sourcecodes ausprobiert aber irgendwie gefällt mir das alles nicht. Jetzt habe ich folgendes selbst versucht und scheitere nur an der Perspektivenkorrektur, bzw. an der richtigen Formel.
Ich habe eine Sphere mit Radius 1, drumherum ist ein ringförmiges Mesh mit demselben Innenradius plus 0,5 Dicke, beides auf 0,0,0. Die Kamera ist Z-5 entfernt und der Ring geht passgenau auf die Sphere über. Der Ring zeigt ständig zur Kamera. Gehe ich nun weiter weg, bleibt alles wie gehabt, gehe ich näher heran wird - bedingt durch die Perspektive der Kamera - die Sphere grösser als der Ring und verdeckt diesen fast ganz, je näher man der Sphere kommt. Jetzt habe ich schon alle möglichen Näherungsversuche gestartet, mit SQR, mit EXP, mit 1/EXP usw... aber es will mir nicht gelingen, dass der Ring im selben Masse grösser wird, wie die Sphere (scheinbar) grösser wird. Ich weiss, dass es funktionieren muss, da ich in einigen Formelversuchen "ins Blaue" einen ähnlichen Skalierungseffekt hinbekommen habe, aber nur näherungsweise (leider nicht gespeichert, waren aber auch haarsträubende Konstrukte). Es geht also nur um die richtige Skalierung des Rings. Vielleicht habt Ihr eine Idee, hier erst einmal der Code zum herumspielen. Zum Testen einfach mit Pfeil-oben mal näher ran an den "Planeten", dann SPACE für Wireframe-Modus und dann den inneren Ringradius mit dem Rand der Sphere vergleichen. Es funktioniert, wenn der Ring - egal wie weit man weg ist - immer genau auf die Sphere aufsetzt. Code: [AUSKLAPPEN] Graphics3D 1024,768,32,2
; Variablengedöns mousespeed#=0.1 cameraspeed#=0.05 camerasmoothness#=10 ; Kamera cam=CreateCamera() PositionEntity cam,0,0,-5 CameraRange cam,0.1,100 ; Planet planet=CreateSphere(32) EntityColor planet,0,255,0 EntityFX planet,1 ; Glow ring=CreateRing(1.25,0.5,60,0,360,1,255,255,255,32,32,32,0) EntityFX ring,1+2+16+32 ; Timer timer=CreateTimer(60) ; Maus in die Mitte MoveMouse GraphicsWidth()/2,GraphicsHeight()/2 While Not KeyHit(1) ; SPACE = Wireframe If KeyHit(57) Then wf=1-wf : WireFrame wf ; Mauskamera mx#=CurveValue(MouseXSpeed()*mousespeed,mx,camerasmoothness) my#=CurveValue(MouseYSpeed()*mousespeed,my,camerasmoothness) MoveMouse GraphicsWidth()/2,GraphicsHeight()/2 pitch#=EntityPitch(cam) yaw#=EntityYaw(cam) pitch=pitch+my yaw=yaw-mx If pitch>89 Then pitch=89 If pitch<-89 Then pitch=-89 RotateEntity cam,0,yaw,0 TurnEntity cam,pitch,0,0 ; Bewegung cx#=(KeyDown(205)-KeyDown(203))*cameraspeed cz#=(KeyDown(200)-KeyDown(208))*cameraspeed MoveEntity cam,cx,0,cz ; Ring zielt auf Kamera, immer 90° gedreht PointEntity ring,cam TurnEntity ring,-90,0,0 RenderWorld WaitTimer timer Flip Wend End ; Smoothcam Function CurveValue#(newvalue#,oldvalue#,increments ) If increments>1 oldvalue#=oldvalue#-(oldvalue#-newvalue#)/increments If increments<=1 oldvalue=newvalue Return oldvalue# End Function ; Single Surface Ring erstellen Function CreateRing(radius#=1.0,width#=1.0,segmente%=360,beginn#=0.0,ende#=360.0,fx%=0,r1%=255,g1%=255,b1%=255,r2%=0,g2%=0,b2%=0,a#=1.0) Local mesh=CreateMesh() Local surf=CreateSurface(mesh) If fx>0 Then EntityFX mesh,fx ;Segmente auf 360 begrenzen If segmente>360 Then segmente=360 ;Step festlegen Local inc#=360/segmente ;Kreisschnitt Beginn a1=beginn ;Volle Kreisdrehung solange im Kreisschnitt While a1<ende ;Winkel a2=(a1+inc) Mod 360 ;Vertexpunkte berechnen v0=AddVertex(surf,(radius-(width/2))*Cos(a1),0,(radius-(width/2))*Sin(a1),0,0) v1=AddVertex(surf,(radius-(width/2))*Cos(a2),0,(radius-(width/2))*Sin(a2),0,0) v2=AddVertex(surf,(radius+(width/2))*Cos(a2),0,(radius+(width/2))*Sin(a2),1,1) v3=AddVertex(surf,(radius+(width/2))*Cos(a1),0,(radius+(width/2))*Sin(a1),1,1) ; Vertex einfärben VertexColor surf,v0,r1,g1,b1,1 VertexColor surf,v1,r1,g1,b1,1 VertexColor surf,v2,r2,g2,b2,a VertexColor surf,v3,r2,g2,b2,a ;Dreiecke basteln AddTriangle surf,v2,v1,v0 AddTriangle surf,v0,v3,v2 ;Step erhöhen a1=a1+inc Wend Return mesh End Function PS: die "Createring" Funktion kann man auch prima dazu verwenden, um z.B. einen Saturnring mit sehr wenigen Tris zu erzeugen, dazu einfach eine Gradienttextur, z.B. von Björn Jonssons Webseite nehmen und auf den Ring klatschen, fertig. |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Sowas stinkt doch gewaltig nach 1 / entfernung oder etwa nicht?
Code: [AUSKLAPPEN] Graphics 800,300,0,2
SetBuffer FrontBuffer() Local X#,Y# For X=0 To 799 Y=(1/X)*300 Plot X,Y Next WaitKey End Da in deinem Beispiel bedingt der Kollision des Planeten immer eine Mindestentfernung zum Mittelpunkt besteht, entstehen auch keine astronomischen Werte. Edit1: mom... Aaaaalso, Der Ring müste ja im grunde ''zusammen klappen'' wenn man es ''realistisch'' haben möchte. Doch wird so ein zusammen klappen doch etwas schwieriger. Man könnte es aber mit deiner Idee auch zum Teil faken, und eine Skallierung muß erst beginnen, nachdem die Wölbung des Planeten durch die Perspektive den Ring-Äquator spürbar überblendet. Edit2: Ähmmm, ok, ich hab eine halbherzige Lösung: Code: [AUSKLAPPEN] PositionEntity ring,EntityX(planet),EntityY(planet),EntityZ(planet)
PointEntity ring,cam TurnEntity ring,-90,0,0 MoveEntity ring,0,1,0 sscale#=12.0/Exp(EntityDistance(ring,cam))+1.1 ScaleEntity ring,sscale,sscale,sscale |
||
Krischan |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Tja, Hectic, das meinte ich mit "näherungsweise" bzw. "haarsträubendes Konstrukt". Leider verschwindet auch hier der Ring völlig hinter der Sphere, sobald man auf eine "ISS-Umlaufbahn" einschwenkt. Ausserdem gibt es jetzt einen kleinen Raum zwischen Ring und Sphere, sobald man weiter weg ist.
Es muss doch irgendeine mathematische korrekte Formel geben. Edit1: setze mal die Cameraposition auf 0,0,-1.2 und füge hinter entityfx ring... ScaleEntity ring,1.8,1.8,1.8 ein. Man muss den Ring nicht "zusammenklappen", es sieht dann auf dieser Höhe schon fast wie eine Atmosphäre aus. Edit 2: die kleine schwarze Störung auf der rechten Seite bekommt man weg, wenn man Createsphere(60) und den Ring auf dieselbe Anzahl Segmente setzt, also: ring=CreateRing(1.25,0.5,60,0,360,1,255,255,255,32,32,32,0) |
||
- Zuletzt bearbeitet von Krischan am Di, Nov 04, 2008 18:50, insgesamt einmal bearbeitet
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das Problem ist einfach dass, wenn man auf den Planeten stehen würde, müßte ja deine Sphäre biszu unendlich lang gestreck sein. Aus diesem Grund wäre ein zusammen klappen der Sphäre sinnvoller, was aber ein ewig neu zu erstellendes Konstrukt bedeuten würde. | ||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Krischan |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Man muss nicht auf dem Planeten stehen, es geht nur um die Distanz, die einer Umlaufbahn entspricht. Also nur die Illusion einer Atmosphäre. | ||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Schlag mich nicht, aber es gibt eine erfreulichere Lösung die auch recht annehmbar ist.
Code: [AUSKLAPPEN] v0=AddVertex(surf,(radius-(width/2))*Cos(a1),0,(radius-(width/2))*Sin(a1),0,0)
v1=AddVertex(surf,(radius-(width/2))*Cos(a2),0,(radius-(width/2))*Sin(a2),0,0) v2=AddVertex(surf,(radius+(width/2))*Cos(a2),-1,(radius+(width/2))*Sin(a2),1,1) v3=AddVertex(surf,(radius+(width/2))*Cos(a1),-1,(radius+(width/2))*Sin(a1),1,1) Edit2: Mir fiel noch auf, dass die Triangles paralell geordnet sind. Bei Kreisen ist das nicht ganz sinnvoll, da man viele Triangles benötigt um solche Helligkeits-Treppeneffekte nicht zu bekommen. Daher bietet es sich an, sie um eine halbe Position zu ''verdrehen''. Siehe selbst und stelle statt 60 nur 20 Segmente dar bei denoch einer besseren Darstellungsqualität. Code: [AUSKLAPPEN] For Winkel=1 To segmente
a1#=Winkel*360/segmente a2#=Winkel*360/segmente +360/segmente a3#=Winkel*360/segmente +180/segmente a4#=Winkel*360/segmente -180/segmente ;Winkel ;Vertexpunkte berechnen v0=AddVertex(surf,(radius-(width/2))*Cos(a1),0,(radius-(width/2))*Sin(a1),0,0) v1=AddVertex(surf,(radius-(width/2))*Cos(a2),0,(radius-(width/2))*Sin(a2),0,0) v2=AddVertex(surf,(radius+(width/2))*Cos(a3),-1,(radius+(width/2))*Sin(a3),1,1) v3=AddVertex(surf,(radius+(width/2))*Cos(a4),-1,(radius+(width/2))*Sin(a4),1,1) ;Vertex einfärben VertexColor surf,v0,r1,g1,b1,1 VertexColor surf,v1,r1,g1,b1,1 VertexColor surf,v2,r2,g2,b2,a VertexColor surf,v3,r2,g2,b2,a ;Dreiecke basteln AddTriangle surf,v2,v1,v0 AddTriangle surf,v0,v3,v2 Next Sorry nur, daß ich dein Code nicht übernommen habe. Hat eine mir nicht so bekannte Vorgehensweise. |
||
Krischan |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich habe jetzt aus lauter Frust darüber eine grelle Sonne draus gemacht, auch ganz nett und ganz ohne Texturen. Kann man auch gut gebrauchen...
Der Teil hier fällt mal wieder unter "näherungsweise": d#=EntityDistance(cam,planet)-0.5 s#=((1.0/d^0.5)*1.33) If s<1 Then s=1 ScaleEntity ring,s,s,s Edit Coool... das läuft ja bei mir mit 2000FPS bei 1920x1200 ![]() Code: [AUSKLAPPEN] Graphics3D 1024,768,32,2
; Variablengedöns mousespeed#=0.1 cameraspeed#=0.05 camerasmoothness#=10 ; Kamera cam=CreateCamera() PositionEntity cam,0,0,-5 CameraRange cam,0.1,100 ; Planet planet=CreateSphere(32) EntityColor planet,255,255,160 EntityFX planet,1 ; Glow ring=CreateRing(1.5,1,90,0,360,1,255,224,128,32,32,32,0) EntityFX ring,1+2+16+32 ; Timer timer=CreateTimer(60) ; Maus in die Mitte MoveMouse GraphicsWidth()/2,GraphicsHeight()/2 While Not KeyHit(1) ; SPACE = Wireframe If KeyHit(57) Then wf=1-wf : WireFrame wf ; Mauskamera mx#=CurveValue(MouseXSpeed()*mousespeed,mx,camerasmoothness) my#=CurveValue(MouseYSpeed()*mousespeed,my,camerasmoothness) MoveMouse GraphicsWidth()/2,GraphicsHeight()/2 pitch#=EntityPitch(cam) yaw#=EntityYaw(cam) pitch=pitch+my yaw=yaw-mx If pitch>89 Then pitch=89 If pitch<-89 Then pitch=-89 RotateEntity cam,0,yaw,0 TurnEntity cam,pitch,0,0 ; Bewegung cx#=(KeyDown(205)-KeyDown(203))*cameraspeed cz#=(KeyDown(200)-KeyDown(208))*cameraspeed MoveEntity cam,cx,0,cz ; Ring zielt auf Kamera, immer 90° gedreht PointEntity ring,cam TurnEntity ring,-90,0,0 d#=EntityDistance(cam,planet)-0.5 s#=((1.0/d^0.5)*1.33) If s<1 Then s=1 ScaleEntity ring,s,s,s RenderWorld WaitTimer timer Flip Wend End ; Smoothcam Function CurveValue#(newvalue#,oldvalue#,increments ) If increments>1 oldvalue#=oldvalue#-(oldvalue#-newvalue#)/increments If increments<=1 oldvalue=newvalue Return oldvalue# End Function ; Single Surface Ring erstellen Function CreateRing(radius#=1.0,width#=1.0,segmente%=360,beginn#=0.0,ende#=360.0,fx%=0,r1%=255,g1%=255,b1%=255,r2%=0,g2%=0,b2%=0,a#=1.0) Local mesh=CreateMesh() Local surf=CreateSurface(mesh) If fx>0 Then EntityFX mesh,fx ;Kreisschnitt Beginn a1=beginn For Winkel=1 To segmente a1=Winkel*360/segmente a2=Winkel*360/segmente +360/segmente a3=Winkel*360/segmente +180/segmente a4=Winkel*360/segmente -180/segmente ;Winkel ;Vertexpunkte berechnen v0=AddVertex(surf,(radius-(width/2))*Cos(a1),0,(radius-(width/2))*Sin(a1),0,0) v1=AddVertex(surf,(radius-(width/2))*Cos(a2),0,(radius-(width/2))*Sin(a2),0,0) v2=AddVertex(surf,(radius+(width/2))*Cos(a3),-1,(radius+(width/2))*Sin(a3),1,1) v3=AddVertex(surf,(radius+(width/2))*Cos(a4),-1,(radius+(width/2))*Sin(a4),1,1) ;Vertex einfärben VertexColor surf,v0,r1,g1,b1,1 VertexColor surf,v1,r1,g1,b1,1 VertexColor surf,v2,r2,g2,b2,a VertexColor surf,v3,r2,g2,b2,a ;Dreiecke basteln AddTriangle surf,v2,v1,v0 AddTriangle surf,v0,v3,v2 Next Return mesh End Function |
||
Krischan |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Sooo... auch mit näherungsweisen Formeln kann man akzeptable Ergebnisse erzielen (solange man mit der Kameranase nicht in die Sphere hineinstubst). In Anlehnung an einen früheren Code hier nenne ich ihn mal "Krischan's toller Planet" - basierend auf dem o.g. Code mit der Modifikation:
d#=EntityDistance(cam,planet) sc#=1.0 If d<10 Then sc=(Exp(1.0/d^3.33)) ScaleEntity ring,sc,sc,sc Das sieht dann hübsch aufpoliert so aus (ist keine Fotomontage, sondern ein Ingame-Screenshot, 8316 Tris bei 1920x1200@550FPS): ![]() ![]() ![]() Den kommentierten Code liefere ich am Wochenende nach - sofern hectic die Sterne gefallen dürfte auch der Sternenalgorithmus von Interesse sein... |
||
Code der Verwirrung |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
sieht alles sehr schön aus...aber:
die atmosphäre scheint überall gleich "hell" zu sein. die dunkle seite des planeten wirkt zu "blau". die angeleuchtete seite und der ring sind sehr gute arbeit. die wolkentextur passt auch super. die plantetenoberfläche sieht prozedual erstellt aus. wenn das so ist hast du richtig gute arbeit geleistet. sieht imho sogar besser aus als bei "infinty"! der weltraumnebel sieht meiner meinung nach etwas zu hell und zu bunt aus. die farbvariation ist zu hoch.ich würde auch den nebel "gewählt" platzieren um den planten noch besser rausstechen zu lassen.manchmal ist weniger mehr. kannst du mir mal erklären wie man den die wolken hinbekommt ? ich bin da momentan "leicht" am verzweifeln.die wolken sind nahezu perfekt! |
||
Omenaton_2 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Gratuliere zu der Lösung mit dem Gloweffekt Korrektur !
Mit diesem Problem hatte ich auch zu kämpfen, ich habe es damals vorläufig aufgegeben. Das fiel mir auch deshalb leicht, weil ich entdeckt hatte, daß es meisten überflüssig ist, sich die ganze Mühe mit so einem 3D Planet zu machen. Es ist viel einfacher den Bild des Planeten samt Atmosphere schön groß auf eine Seite des Skyboxes zu setzen. Ein Planet dreht sich so langsam, daß die Bewegung gar nicht wahrnehmbar ist. Wenn der Planet sich praktisch nicht bewegt, dann kann es auch einfach als Standbild da sein. In meinem Spiel fliegt man nie zu nahe an den Planeten ran, deshalb stört es nicht, wenn die Größe sich nicht ändert. Die Wolken und die Sterne sind auch sehr schön. Ich finde die Farbigkeit ist auch richtig, es ist nicht zu bunt. Das ist gut als eine Variante. Du machst bald bestimmt noch mehr Hintergründe, die dann weniger bunt sein werden. |
||
Krischan |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Juchhu ich habe die mathematisch exakte Lösung herausgefunden. Man braucht nur zwei rechtwinklige Dreiecke und etwas Trigonometrie. Das Licht ging mir beim Betrachten dieser Homepage auf.
Die gesuchte Skalierung des Rings ist identisch mit der C2 Hypotenuse des zweiten Dreiecks. Ich habe die Variablen so genannt, wie sie im Dreieck benannt würden. Wir benötigen nur die Scale (den Radius des Planeten) und die Distanz zwischen der Kamera und dem Planetenzentrum, der Rest ist simpel wenn man das Prinzip verstanden hat. Hier eine einfache Zeichnung der zwei Dreiecke, der rote Punkt oben ist die Kamera, die rote Linie die Distanz, die schwarze Linie der Radius und die violette Linie die gesuchte C2 Hypotenuse, nach der wir suchen. ![]() radius#=scale distance#=EntityDistance(cam,planet) ; First triangle c1#=distance a1#=radius q1#=a1^2/c1 p1#=c1-q1 h1#=Sqr(p1*q1) gamma1#=90 alpha1#=ATan(h1/p1) beta1#=gamma1-alpha1 ; Second Triangle alpha2# = 90-(90-beta1) b2# = a1/Tan(alpha2) c2# = (Sqr(a1^2 + b2^2))/radius ScaleEntity ring,c2,c2,c2 Code: [AUSKLAPPEN] Graphics3D 1024,768,32,2
; Variables mousespeed#=0.1 cameraspeed#=0.01 camerasmoothness#=10 scale#=1.0 timer=CreateTimer(60) ; Camera cam=CreateCamera() PositionEntity cam,0,0,-scale*2 CameraRange cam,0.01,1000 ; Planet planet=CreateSphere(60) ScaleEntity planet,scale,scale,scale EntityColor planet,0,255,0 ring=CreateRing(1*scale,1.5*scale,120,1+2+32,3,192,224,255,64,128,255,0,scale) MoveMouse GraphicsWidth()/2,GraphicsHeight()/2 While Not KeyHit(1) If KeyHit(57) Then wf=1-wf : WireFrame wf ; Mousecam mx#=CurveValue(MouseXSpeed()*mousespeed,mx,camerasmoothness) my#=CurveValue(MouseYSpeed()*mousespeed,my,camerasmoothness) MoveMouse GraphicsWidth()/2,GraphicsHeight()/2 pitch#=EntityPitch(cam) yaw#=EntityYaw(cam) pitch=pitch+my yaw=yaw-mx If pitch>89 Then pitch=89 If pitch<-89 Then pitch=-89 RotateEntity cam,0,yaw,0 TurnEntity cam,pitch,0,0 ; Movement cx#=(KeyDown(205)-KeyDown(203))*cameraspeed cz#=(KeyDown(200)-KeyDown(208))*cameraspeed MoveEntity cam,cx,0,cz PointEntity ring,cam radius#=scale distance#=EntityDistance(cam,planet) ; First triangle c1#=distance a1#=radius q1#=a1^2/c1 p1#=c1-q1 h1#=Sqr(p1*q1) gamma1#=90 alpha1#=ATan(h1/p1) beta1#=gamma1-alpha1 ; Second Triangle alpha2# = 90-(90-beta1) b2# = a1/Tan(alpha2) c2# = (Sqr(a1^2 + b2^2))/radius ScaleEntity ring,c2,c2,c2 RenderWorld WaitTimer timer Flip 0 Wend End ; Smoothcam Function CurveValue#(newvalue#,oldvalue#,increments ) If increments>1 oldvalue#=oldvalue#-(oldvalue#-newvalue#)/increments If increments<=1 oldvalue=newvalue Return oldvalue# End Function ; Ring Function CreateRing(radius1#=1.0,radius2#=2.0,segments%=360,fx%=0,blend%=0,r1%=255,g1%=255,b1%=255,r2%=0,g2%=0,b2%=0,a#=1.0,scale#=1.0) Local a1#,a2#,a3#,a4#,angle% Local mesh=CreateMesh() Local surf=CreateSurface(mesh) ; Limit segments If segments>360 Then segments=360 ; Create ring For angle=1 To segments a1=angle*360.0/segments a2=angle*360.0/segments +360.0/segments a3=angle*360.0/segments +180.0/segments a4=angle*360.0/segments -180.0/segments ; Calc vertex points v0=AddVertex(surf,radius1*Cos(a1),radius1*Sin(a1),0,0,0) v1=AddVertex(surf,radius1*Cos(a2),radius1*Sin(a2),0,0,0) v2=AddVertex(surf,radius2*Cos(a3),radius2*Sin(a3),0,1,1) v3=AddVertex(surf,radius2*Cos(a4),radius2*Sin(a4),0,0,1) ; Color VertexColor surf,v0,r1,g1,b1,1 VertexColor surf,v1,r1,g1,b1,1 VertexColor surf,v2,r2,g2,b2,a VertexColor surf,v3,r2,g2,b2,a ; Create Triangles AddTriangle surf,v2,v1,v0 AddTriangle surf,v0,v3,v2 Next If fx>0 Then EntityFX mesh,fx If blend>0 Then EntityBlend mesh,blend Return mesh End Function Jetzt muss ich mich mit der Beleuchtung des Rings näher auseinandersetzen, der Weltraumnebel ist nur die erste Version und kann noch angepasst werden, ich brauchte erst einmal einen schicken Hintergrund als Motivationsbeschleuniger (soviel zum Thema "zu bunt" ![]() @Code der Verwirrung Ja, das ist ein prozedural erstellter Planet, mit Hilfe dieses Scripts (3D Perlin Noise) und ein wenig Gradientverlauf in Photoshop - diesen Step muss ich noch BB-mässig automatisieren. Die Wolken habe ich von der Celestia Motherlode Homepage entnommen, ist eine verbesserte Version der Nasa Blue Marble Textur, "nur" halt transparent. Sieht einfach nur geil aus. Link zur Wolkentextur (2048x1024 PNG24) Zusätzlich hat der Planet noch eine Entityshininess von 0.25, eine Normalmap mit Textureblend 4, eine Detailmap und eine Spherical Reflection map (Loadtexture Flag 64). Wenn alles soweit fertig ist poste ich mal den Code mit Media im Codearchiv. @Omenaton_2 Ich brauche für meinen Fall aber einen 3D Planeten, meine Planungen gehen ja noch viel weiter. Die letzten Wochen habe ich mich damit beschäftigt, wie man ein Sonnensystem mit 10 Mrd. km Durchmesser mit einer Camerarange von nur 1,10000 darstellt. Da kommt man bei einer 1:1 Darstellung schnell ins Straucheln (Floatproblem). Meine Lösung beruht hier auf exponentieller Vergrösserung / Verkleinerung des gesamten Systems unter Berücksichtigung zum nächsten Planeten, der dann X-fach vergrössert dargestellt wird. Auch die Anfluggeschwindigkeit wird entsprechend skaliert. Mein Ziel ist es, nicht nur eines sondern dutzende oder hunderte Sonnensysteme prozedural zu erstellen, und zwar mit nahtlosem Flug durch den Weltraum zwischen den Systemen und Planeten. Vielleicht gibt es mal ein Projekt oder sogar ein Spiel, im Moment sind das nur zusammenhangslose Techdemos. 3D Perlin Noise Planet, bereits für die Nutzung auf einer Sphere verzerrt:Code: [AUSKLAPPEN] Function DBInt( x# )
If x >= 0 Return Floor(x) Else Return Ceil(x) End If End Function xs%=512 ys%=256 start=MilliSecs() Graphics xs,ys,32,2 ; create arrays For perlin generator Dim s#(15,2) Dim r#(63,63,63) ; prepare the perlin prepare_perlin(42,0.66) ; multisampling controller multi% = 1 milti% = multi - 1 malt# = multi ^ 2 malt# = 1 / malt# xsize1% = xs ysize1% = ys ; get the base sizes xsize2% = xsize1 * multi ysize2% = ysize1 * multi ; get the scalers xscaler1% = 360 yscaler1% = 180 xscaler2# = xscaler1*1.0 / xsize2 yscaler2# = yscaler1*1.0 / ysize2 width# = 2 ; piece details pxs% = xs-1 pys% = ys-1 xof% = 0 yof% = 0 SetBuffer FrontBuffer() image=CreateImage(xs,ys) ib=ImageBuffer(image) LockBuffer ib min=255 max=0 ; loop the y position For posx% = 0 To pxs Step 1 ; loop the x For posy% = 0 To pys Step 1 ; reset colours g = 0 b = 0 ; get the scaled sizes xp1% = (posx + xof) * multi yp1% = (posy + yof) * multi ; do the multisampling For posa% = 0 To milti ; get the baring around the sphere ba# = xp1 + posa ba# = (ba# + 0.5) * xscaler2# xp2# = Cos(ba#) zp2# = Sin(ba#) For poss% = 0 To milti ; get the pitch around the sphere pa# = yp1 + poss pa# = ((pa# + 0.5) * yscaler2#) po# = Sin(pa#) * width# ; get the positions in the space x# = (xp2# * po#) + 5 y# = (Cos(pa#) * width#) + 5 z# = (zp2# * po#) + 5 ; get the perlin result For that part h = DBInt(perl(x#,y#,z#,7) * 255) ; cap the value If h => 255 Then h = 255 If h <= 0 Then h = 0 If h>max Then max=h If h<min Then min=h ; failsafe quit If KeyHit(1) Then End Next Next ; scale down the colours c=c*malt# ;Color h,h,h ;Plot posx,posy ;g = g * malt# ;b = b * malt# ; get the colour rgb=h*$10000+h*$100+h ; put a dot there WritePixelFast posx,posy,rgb,ib Next Next For posx = 0 To pxs Step 1 For posy = 0 To pys Step 1 rgb=ReadPixelFast(posx,posy,ib) r1=(rgb And $ff0000)/$10000 h=Normalisieren(r1,min,max,0,255) rgb=h*$10000+h*$100+h WritePixelFast posx,posy,rgb,ib Next Next UnlockBuffer ib ende=MilliSecs() While Not KeyHit(1) DrawImage image,0,0 If KeyHit(57) Then SaveBuffer(ib,"planet.bmp") : End Text 0,0,(ende-start) Flip Wend End ; perlin Function Function perl#(x#,y#,z#,octaves%) ; make sure the pass value is zerod h# = 0 ; shift octaves down to Input works from 1 but system works from 0 octaves=octaves-1 ; make sue octaves are an ecceptable value If octaves <= 0 Then octaves = 0 If octaves => 15 Then octaves = 15 ; loop the octaves For oct% = 0 To octaves ; grab the frequency And amplitude For this fre# = s#(oct,0) amp# = s#(oct,1) ; convert the co-ordinates into steps xx = DBInt(x# * fre#) yy = DBInt(y# * fre#) zz = DBInt(z# * fre#) ; get the inbetween co-ords xb# = sine((x# * fre#) - flo(xx)) yb# = sine((y# * fre#) - flo(yy)) zb# = sine((z# * fre#) - flo(zz)) xa# = 1 - xb# ya# = 1 - yb# za# = 1 - zb# ; get the values For the 8 corners v000# = vil(xx,yy,zz) * xa# * ya# * za# v100# = vil(xx+1,yy,zz) * xb# * ya# * za# v010# = vil(xx,yy+1,zz) * xa# * yb# * za# v001# = vil(xx,yy,zz+1) * xa# * ya# * zb# v101# = vil(xx+1,yy,zz+1) * xb# * ya# * zb# v110# = vil(xx+1,yy+1,zz) * xb# * yb# * za# v011# = vil(xx,yy+1,zz+1) * xa# * yb# * zb# v111# = vil(xx+1,yy+1,zz+1) * xb# * yb# * zb# ; add it on h#=h#+(v000# + v100# + v010# + v001# + v101# + v110# + v011# + v111#) * amp# Next ; scale it down h# = h# * s#(octaves,2) Return h# End Function ; Function to get the random value of a co-ordinate Function vil#(x,y,z) ; control edges If x < 0 Then x = x - (DBInt((x / 64) - 1) * 64) Else x = x - (DBInt(x/64) * 64) If y < 0 Then y = y - (DBInt((y / 64) - 1) * 64) Else y = y - (DBInt(y/64) * 64) If z < 0 Then z = z - (DBInt((z / 64) - 1) * 64) Else z = z - (DBInt(z/64) * 64) ; get the number v# = r#(x,y,z) Return v# End Function ; Return an integer as a floating point Function flo#(a) b# = a*1.0 Return b# End Function ; Function to turn a straight 0 - 1 into a sine curved 0 - 1 Function sine#(v#) ; perform the change v# = (1 - Cos(v# * 180)) * 0.5 Return v End Function ; Function to prepare Data For perlin noise Function prepare_perlin(seed,persistance#) ; set the seed value SeedRnd seed ; create seed Data For x = 0 To 63 For y = 0 To 63 For z = 0 To 63 zz# = Rnd(10000) r#(x,y,z) = (zz# * 0.0001) Next Next Next ; prepare octave Data For i = 0 To 15 ; work out the frequence of the octave s#(i,0) = 2 ^ i ; get the amplitude s#(i,1) = persistance# ^ i ; work out the maximum amplitude of s#(i,2) = 0.0 For j = 0 To i s#(i,2)=s#(i,2)+s#(j,1) Next s#(i,2) = 1.0 / s#(i,2) Next End Function Function Normalisieren#(value#=128.0,value_min#=0.0,value_max#=255.0,norm_min#=0.0,norm_max#=1.0) Return ((value-value_min)/(value_max-value_min))*(norm_max-norm_min)+norm_min End Function Hier die Planetentextur, die ich für meine Screenshots verwendet habe: ![]() |
||
Code der Verwirrung |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
erstmal danke für die wolkentextur!
und ich hätte da noch ne frage: wie schaffst du es die textur so zu verzerren? ich hab ewig nach ner möglichkeit gesucht sowas hinzubekommen.(sry aber ich verstehe erlichgesagt den code nicht so ganz) und wird die textur nicht pixelig wenn man sich den planet aus der nähe betrachtet? bei vielen spielen wurde das (auf eine mir rätselhafte art und weise ![]() |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Um feinere Strukturen auf einer Oberfläche zu bekommen wird meisten Multitexturing benutzt. Damit aber die UV-Koordinaten nicht auf allen Texturen gleich sind, kann man sich unter Blitz3D zum Beispiel mit ScaleTexture![]() @Krischan, deine neue Version sieht schon viel besser aus. Aber ich finde 120 Segmente schon höhst übertrieben. Bereits mit 20 Segmenten kann man gut damit leben. Bei 30 Segmenten muß man schon genau hinsehen (und vorher auch wissen) um es zu erkennen. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Krischan |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ehrlich gesagt verstehe ich den Code zur Planetentexturerzeugung auch nur halb, den habe ich nur von Darkbasic portiert. Nur so viel: es handelt sich hierbei um 3D Perlin Noise, also eine Wolkentextur, die auch noch in die dritte Dimension hineinreicht. Am Besten kann man sich das anhand des folgenden Bildes veranschaulichen:
![]() Stell Dir vor, Du schneidest jetzt mit einem Messer eine Scheibe aus dem Würfel heraus, dann hast Du eine 2D Wolkentextur. Wenn Du nun anstatt einer Scheibe eine Kugel aus dem Würfel schneidest und die Koordinaten der 3D-Kugel auf eine 2D Zylindertextur umrechnest, erhälst Du das Bild, welches der Code berechnet. Dabei wird anscheinend zu den Polen hin zusätzlich verzerrt. Noch genialer wäre es, direkt aus der Wolke eine Kugel oder Geosphere mit Vertices heraus zu "meisseln", wobei dann der Radius mal die "Höhe" des Perlinwertes die Erhöhung des Vertexpunktes ergibt, also z.B. die Höhe eines Berges oder Tiefe eines Tales auf dem Planeten. Und wenn man jetzt noch ein LOD-System dazu bastelt kann man einen Planeten bis auf Metergrösse (je nach Floatgenauigkeit) erstellen! Genaueres zu dem Thema kannst Du Dir hier anschauen: Mein altes Thema im BB-Forum zum Thema Spherical Mapping Infinity kennst Du ja, der Vollständigkeit halber Hier ein Video von Infinity, wie es aussieht, wenn man es richtig macht Ein Darkbasic-Beispiel, wie man das mit der Geosphere und dem LOD umsetzen kann Der letzte Code ist mir persönlich zu hoch, aber die Demo ist relativ einfach gehalten und sehr anschaulich. Wenn jemand das Infinity-Prinzip in Blitz3D hinbekäme wäre das mein persönlicher heiliger Gral der Spacesimulationen in Blitz. Mein Planet wird natürlich pixelig bzw. verwaschen, um das etwas zu kaschieren benutze ich die Wolkentextur und eine Detailtextur, damit das nicht so gleich ins Auge fällt. Mein Raumschiff fliegt sowieso nur max. auf ISS-Umlaufbahngrösse heran. Mein Ziel war es lediglich, einen Planeten ähnlich wie die in Freelancer zu basteln und das ist mir soweit ich das beurteilen kann gut gelungen (wobei der Freelancer-Planet noch ein einfaches LOD-System benutzt und die Details bei Annäherung erhöht, kann man gut beim Planeten "Leeds" erkennen, der hat so eine Zufalls-beleuchtete-Stadtstruktur). Anscheinend wird da aber nur ein wenig subdivided. |
||
Krischan |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Jaja hectic, hast ja recht. Aber schau Dir mal "unsere" Ringfunktion an, da hab ich noch was dran korrigiert, bei Dir waren die UVs durcheinander. Jetzt kann man da auch eine Textur drauflegen (also einen Farbverlauf von links nach rechts, wobei links die Planetenoberfläche und rechts der Weltraum sind). | ||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
ok, die UV-Koordinaten habe ich garnicht berücksichtigt. Mir ging es erstmal um den Ring selbst.
Nur eine Frage: Lädst du die Texturen so, wie sie auf dem von dir geposteten Link zu sehen sind? Ich bin mir zwar nicht sicher, aber es könnte sein, dass einige Grafikkarten daraus dann eine 2048x2048er Textur machen. Das ist sehr verschwenderisch. aus diesem Grund habe ich mir mal folgendes erlaubt aus dem ersten Bild deines Links auszuprobieren. http://www.hectic.de/data/ring.rar Die Textur sieht in meinem Beispiel wie unten aus. Sie ist 128x128 Pixel groß und beinhaltet eine volle 1024er Breitenauflösung. Wie man sieht, könnte man das ganze noch ohne Einschränkung auf 64x64 bringen. Dazu dann die lila Lücken stopfen und den Streifen 4 Pixel hoch statt 8 (-2 Rand) machen. ![]() |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Code der Verwirrung |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@hectic:
mir ist klar, dass man mit scaletexture einiges an detail rausholen kann, aber dann würde es an den polen texturstauchungen geben. ich habe bisher keine möglichkeit gefunden das zu verhindern. bei spielen wie z.b. X3 Terran Conflict wurden 1024 er texturen aneinandergereiht ohne verzerrung an den polen. dummerweise komme ich nicht drauf, wie die uvw map aussehen muss. |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mit einer gewöhnlichen CreateSphere![]() |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Krischan |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Interessant. An sowas hatte ich bislang noch gar nicht gedacht. Wie müsste das aussehen, um es in unsere Ringfunktion einzubauen? Für das Rendering hatte ich nur schnell was zusammengehauen:
![]() Basierend auf Björn Jonssons exzellenten Grafiken (ich glaube Forward+Color multiplied und Transparenz in den Alphakanal gehauen). |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Der UV-Koordinaten-Zugriff erfolg liniear. Ich habe noch nicht ganz verstanden warum in deinem letzten Beispiel das nicht ganz der Fall ist. Da liesst du mit 00-00-11-01 ein Dreieck aus. Es müsste auch (links/rechts) 00-00-10-10 oder (oben/unten) 00-00-01-01 auch gehen. Daher ergibt sich bereits die Frage.
Zu meinem Beispielbild. Dieses habe ich vorhin manuell erstellt und dauerte etwa 10-15 min. Für alle Bilder würde es sich also lohnen sich ein kleines Programm zu schreiben, welches das tut. Das sollte dann auf 2D-Ebene geschehen. Das auslesen der UV-Koordinaten muß dann recht genau sein, denn sonst gerät man leicht aus den Streifen und es sieht dan blöd aus. Edit1: Ich hab mal grad was geschrieben http://www.hectic.de/data/ring.rar Hat nun volle 1500 Pixel Breite. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group