Leistungsverbesserung

Übersicht BlitzBasic Allgemein

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

Noobody

Betreff: Leistungsverbesserung

BeitragSo, Dez 09, 2007 13:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Als ich gestern auf Wikipedia gestöbert habe, ist mir ein Artikel über Metaballs ins Auge gesprungen.
Weil diese mich interessiert haben, hab ich eine kleine Simulation in B3D geschrieben.
Sie läuft ganz gut, nur zwingen bereits 20 - 30 Metaballs meinen Rechner trotz Banks und WritePixelFast in die Knie.
Mir war schon klar, dass die Berechungen rechenintensiv wären, aber so heftig hätte ich es nicht erwartet.
Da mir nicht einfällt, wo ich jetzt das Programm leistungssparender machen könnte, dachte ich, ich wende mich an die liebe Community.

Hier mein Code:
Code: [AUSKLAPPEN]
Graphics 800, 600, 0, 2
SetBuffer BackBuffer()

AppTitle "Metaballs"

Type Metaball
   Field X#
   Field Y#
   Field XVector#
   Field YVector#
   Field Charge
End Type

Const Treshold# = 30
Const MaxRadius = 30

Global Sums = CreateBank( 800*600*4 )

CreateMetaballs( 30 )

Timer = CreateTimer( 60 )

While Not KeyHit( 1 )
   Cls
   UpdateMetaballs()
   RenderMetaballs()
   Flip 0
   WaitTimer Timer
Wend

End

Function CreateMetaballs( Count )
   For i = 0 To Count - 1
      Blinn.Metaball = New Metaball
         Blinn\X# = Rnd( 100, 500 )
         Blinn\Y# = Rnd( 100, 500 )
         Blinn\XVector# = Rnd( -2, 2 )
         Blinn\YVector# = Rnd( -2, 2 )
         While Blinn\Charge = 0
            Blinn\Charge = Rnd( -3, 3 )
         Wend
   Next
End Function

Function UpdateMetaballs()
   For Jim.Metaball = Each Metaball
      Jim\X# = Jim\X# + Jim\XVector#
      Jim\Y# = Jim\Y# + Jim\YVector#
      IntX = Floor( Jim\X# )
      IntY = Floor( Jim\Y# )
      
      For i = 0 To 2*MaxRadius
         For t = 0 To 2*MaxRadius
            Offset = ( IntX - MaxRadius + i + ( IntY - MaxRadius + t )*800 )*4
            Sum# = PeekFloat( Sums, Offset )
            If i = MaxRadius And t = MaxRadius Then
               Value# = Treshold
            Else
               Value# = 1000/( i*i - 2*i*MaxRadius + t*t - 2*t*MaxRadius + 2*MaxRadius*MaxRadius )
            EndIf
            PokeFloat( Sums, Offset, Sum# + Jim\Charge*Value# )
         Next
      Next
      
      If Jim\X# < 2*MaxRadius Then
         Jim\X# = 800 - 2*MaxRadius
      ElseIf Jim\X# > 800 - 2*MaxRadius Then
         Jim\X# = 2*MaxRadius
      EndIf
      
      If Jim\Y# < 2*MaxRadius Then
         Jim\Y# = 600 - 2*MaxRadius
      ElseIf Jim\Y# > 600 - 2*MaxRadius Then
         Jim\Y# = 2*MaxRadius
      EndIf
   Next
End Function

Function RenderMetaballs()
   LockBuffer BackBuffer()
   
   For Blinn.Metaball = Each Metaball
      IntX = Floor( Blinn\X# )
      IntY = Floor( Blinn\Y# )
      OldX = Floor( Blinn\X# - Blinn\XVector# )
      OldY = Floor( Blinn\Y# - Blinn\YVector# )
      
      For i = 0 To 2*MaxRadius
         For t = 0 To 2*MaxRadius
            Offset = ( IntX + i - MaxRadius + ( IntY + t - MaxRadius )*800 )*4
            Sum# = PeekFloat( Sums, Offset )
            If Sgn( Sum# ) = 1 Then
               If Sum# >= Treshold Then WritePixelFast IntX + i - MaxRadius, IntY + t - MaxRadius, $00FFFFFF
            ElseIf Sgn( Sum# ) = -1 Then
               If Abs( Sum# ) >= Treshold Then WritePixelFast IntX + i - MaxRadius, IntY + t - MaxRadius, $00FF0000
            EndIf
         Next
      Next
   Next
   
   ResizeBank Sums, 0
   ResizeBank Sums, 800*600*4
   
   UnlockBuffer BackBuffer()
End Function


Negativ geladene Metaballs sind rot, positive Weiss dargestellt (unterschiedlich geladene Metaballs drücken sich ein, gleichgeladenen ziehen sich an).
Ich hoffe, ihr könnt mir dabei helfen.

MfG
Noobody
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSo, Dez 09, 2007 13:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich würd's mit Blitz3D versuchen, und zwar, Grauton von 128,128,128 als Hintergrund. Dann schwarze und weiße Metaballs mit weiten Kontrastverlauf drauf rendern. Das Ergebnis dann verwerten und als 2D anzeigen (dunkler als 128 = rot, heller als 128 = weiß) lassen.

Ob es nach deinen kriterien funktioniert weiß ich nicht, aber es wäre eventuell ein Versuch wert. Nachteil ist, dass die Verwertung eben viel Zeit in Anspruch nimmt. Vorteil ist, dass die Anzahl der Metaballs keine oder kaum sich auf weitere Performenceeinbussen auslegen.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D

Noobody

BeitragSo, Dez 09, 2007 14:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Es wäre einen Versuch wert, wenn ich deine Antwort verstehen würde... *amkopfkratz*
Was meinst du mit "mit weitem Kontrastverlauf drauf rendern"?
Meinst du, 3D - Objekte zu nehmen und mit diesen die Berechnung durchführen?
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Foppele

BeitragSo, Dez 09, 2007 14:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich find's jetzt schon ziemlich cool, aber in 3D wird kaum in einer vernünftigen Geschwindigkeit gehen. Auf die gleiche Weise kann man z.B. Flüssigkeiten simulieren, es gibt auch einige Programme die das mit relativ wenigen Metaballs in annährend Echtzeit hinkriegen.

[EDIT] hectic meinte glaub ich was anderes...

Noobody

BeitragSo, Dez 09, 2007 14:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich bezweifle auch, dass das in 3D so ohne weiteres ginge, ohne dass gleich der Grossteil der Rechenleistung für die Berechnung der Flüssigkeit draufgeht.
Nach einigen Geschwindigkeitstests geht für die Berechnung der Metaballs ein wenig mehr Zeit drauf als für das Rendern, aber unter 60 Metaballs brauchen beide ungefähr die gleiche Zeit.
Ist ja auch logisch, da beide die beiden For - Schleifen durchlaufen müssen. Eine Möglichkeit sähe ich auch darin, den MaxRadius für jeden Metaball zu berechnen, so dass für die kleinen Bälle keine Punkte in irrelevanter Entfernung berechnet werden.
Sowas wie ein minimaler Radius, der von der Stärke der Ladung eines Metaballs beeinflusst wird.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Foppele

BeitragSo, Dez 09, 2007 14:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Gehen tut das schon, die Anzahl der Metaballs ist natürlich sehr begrenzt für ein Echtzeitergebnis.

Noobody

BeitragSo, Dez 09, 2007 15:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Das mit dem MaxRadius habe ich ausprobiert und es bringt schon eine Geschwindigkeitssteigerung.
Nur kommt es manchmal vor, dass Metaballs 'ausfransen', wenn sie aneinandertreffen, aber das fällt nicht gross auf.
Aber ein Grossteil der Rechenarbeit beim Updaten der Metaballs geht dabei drauf:
Code: [AUSKLAPPEN]
Value# = 1000/( i*i - 2*i*MaxRadius + t*t - 2*t*MaxRadius + 2*MaxRadius*MaxRadius )


Wenn es eine Möglichkeit gäbe, diese Rechnung zu vereinfachen, dann wäre ich schon einen Schritt weiter.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Dreamora

BeitragSo, Dez 09, 2007 17:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Da gibts nur genau 2 Vereinfachungen:
Vor das gesamte loopkonstrukt (was aus meiner sicht das hauptproblem ist, eine 4fach loop ist ein massives problem!) einfach

MaxRadiusx2# = maxradius *2
MaxRadius2x2# = 2 * maxradius * maxradius

und dann drinnen die benutzen.
Das senkt den Berechnungsaufwand schon ma um ein grösseres wenig
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Noobody

BeitragSo, Dez 09, 2007 18:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Das mit der Loop ist mir bewusst, nur ist mir kein anderer Weg eingefallen, wie man für alle Punkte in der Umgebung des Metaballs die Verteilung berechnet und diese danach zeichnet.
Könnte es etwas bringen, das Zeichnen und das Berechnen in einem Schritt unterzubringen?
Zwar würde dann entweder das gleiche Pixel mehrmals überschrieben bzw. man müsste feststellen, ob sich in Zukunft das Pixel verändert, wenn nicht, dann zeichnen.

EDIT: Ich habe das ausprobiert, und die Zeit zum Berechnen + Render ist bei 60 Metaballs ~10 Millisekunden kürzer.
Allerdings werden die Metaballs nicht mehr ganz richtig gezeichnet, sondern überlagern sich (was sie ja eigentlich nicht dürften) bei Berührungen mit anders geladenen Metaballs.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Matthias

BeitragSo, Dez 09, 2007 18:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Hay. Interessant Interessant.

Meistens sind die Einfachsten sachen auch die langsamsten.

Das heist Types sind zwar sehr Konfortabel aber auch langsamm.
Banks sind zwar schneller aber immer noch nicht so schnell wie Dim Felder
Am Schnellsten sind Eindimensoinale Int DimFelder.

Auserdem sollte mann auf Projekte die auf Speed ausgelegt sind auch versunchen mehrere Rechenoperationen zusammen zu fassen. Ubnd zwichenschen zu speichern zb wie Dremora schon schrieb.

Naja schlusendlich. War der Schlüssel das vorberechnen und die Daten in ein dim Feld abzuspeichern.

Als ich begonnen hatte, hatte ich bei 30Bälle 22FPS
Nun sinds 60Bälle bei 36-38FPS. 1,7GHz

Hoffe ich konnte dir Helfen.

Code: [AUSKLAPPEN]


Graphics 800, 600, 32, 2
SetBuffer BackBuffer()
Global MaxBalls

Dim tVorb(100),rVorb(100),qVorb(100)
Dim Map(1024*1024)


AppTitle "Metaballs"



Dim MetaX#(1000)
Dim MetaY#(1000)
Dim MetaXVector#(1000)
Dim MetaYVector#(1000)
Dim MetaChange#(1000)
Dim Matrix#(10,2500)




Const Treshold# = 30
Const MaxRadius = 30

;--------Vorberechnen----------------
For U=1 To 5:For i=0 To 2499
Matrix(U-1,I)=Ceil((1000/Float(I))*U)
Next:Next
MR=MaxRadius*2:MRR=MR*MaxRadius
For z=0 To 67

tVorb(z)=z*z
rVorb(z)=z*(MaxRadius)*2
 
qVorb(z)=(tVorb(z)-rVorb(z))

Next




CreateMetaballs(60)

Timer = CreateTimer(60)
SetBuffer BackBuffer()
While Not KeyHit( 1 )
FPSz=FPSz+1:M=MilliSecs()
If M>FPSt Then FPS=FPSz:FPSz=0:FPSt=M+999

   Cls
   UpdateMetaballs()
   RenderMetaballs()
   
 
Text 10,10,FPS

Flip 0


Wend

End

Function CreateMetaballs(Count)
   MaxBalls=Count-1
      For B = 0 To MaxBalls
   
         MetaX(B) = Rnd( 100, 500 )
         MetaY(B) = Rnd( 100, 500 )
         MetaXVector(B) = Rnd( -2, 2 )
         MetaYVector(B) = Rnd( -2, 2 )
         
         While MetaChange(B)=0
             
            MetaChange(B)=Rand(-4,4)
         Wend
       Next
End Function

Function UpdateMetaballs()
For B=0 To MaxBalls
     MetaX(B)=MetaX(B) + MetaXVector(B)
     MetaY(B)=MetaY(B) + MetaYVector(B)


If MetaX(B)< 2*MaxRadius Then
         MetaX(B)= 800 - 2*MaxRadius
      ElseIf MetaX(B)> 800 - 2*MaxRadius Then
        MetaX(B) = 2*MaxRadius
      EndIf
       
      If MetaY(B) < 2*MaxRadius Then
        MetaY(B)=600 - 2*MaxRadius
      ElseIf MetaY(B)> 600 - 2*MaxRadius Then
         MetaY(B)= 2*MaxRadius
      EndIf








      IntX = Floor(MetaX(B))
      IntY = Floor(MetaY(B))
       MR=MaxRadius*2:MRR=MR*MaxRadius
       
      For i = 0 To MR:iquad=qVorb(i)+MRR:No=0
          px=IntX+i-MaxRadius:If i=MaxRadius Then No=1
         For t = 0 To MR:py=IntY+t-MaxRadius:Offset=px Shl 10+py:Japp=1
           If No=1 Then
               If t=MaxRadius And MetaChange(B)>0 Then Map(Offset)=1000:Japp=0
               If t=MaxRadius And MetaChange(B)<0 Then Map(Offset)=-1000:Japp=0
           End If
           If Japp=1 Then
            Sgnn=1:Ch=MetaChange(B):If Ch<0 Then Sgnn=-1:Ch=Ch*-1
                   re=iquad+qVorb(t):If ch=0 Then End
             Map(Offset)=Map(Offset)+Matrix(Ch,re)*Sgnn
           End If
         Next
     Next
       
     

     
   Next
End Function

Function RenderMetaballs()
 
 LockBuffer BackBuffer()
   
   For B=0 To MaxBalls
      IntX = Floor(MetaX(B))
      IntY = Floor(MetaY(B))
      OldX = Floor(MetaX(B)-MetaXVector(B))
      OldY = Floor(MetaY(B)-MetaYVector(B))
      MR=MaxRadius*2+1
      For i = 0 To MR
         px=IntX+i-MaxRadius
       



         For t =0 To MR
            py=IntY+t-MaxRadius:Offset=px Shl 10+py
                 Sum=Map(Offset):Map(Offset)=0
                                             
                     

            If Abs(Sum)=>Treshold Then 
           
              If Sum>0 Then
                   WritePixelFast px,py,$00FFFFFF
              Else
                 WritePixelFast px,py, $00FF0000 
              End If
           End If
             



         Next
      Next
   Next

   UnlockBuffer BackBuffer()
End Function


Gruß Matthias

*Editiert
  • Zuletzt bearbeitet von Matthias am So, Dez 09, 2007 20:49, insgesamt 2-mal bearbeitet

Noobody

BeitragSo, Dez 09, 2007 19:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Das mit den Arrays wusste ich jetzt nicht, ebensowenig wie das mit den Types.
Ich hatte von Anfang an das Gefühl, dass Banks generell schneller wären als Arrays.
In deinen Code muss ich mich erst noch richtig reinwerfen, aber ein paar Dinge sind mir beim überfliegen aufgefallen:
- Charge war schon richtig vorher (engl für Ladung), Change als Array - Name hätte hier keinen Sinn bezüglich Funktion
- Wenn Metaballs an den Rändern verschwinden, lassen sie hässliche Rechtecke und Streifen zurück - weil die Restladung nicht aus dem Array gelöscht wurde. Vorhere konnte das bequem dadurch gemacht werden, die Bankgrösse zurückzusetzen. Ginge hier auch mit Arrays, aber wie schnell das ist, weiss ich nicht.
- In der Mitte der Metaballs erscheinen manchmal schwarze/weisse Punkte, was aber daran liegt, dass der Mittelpunkt die Ladung des Schwellenwerts erhält. Fliegt ein anderer Metaball vorbei und ändert die Ladung nur leicht, sieht man einen schwarzen Punkt.

Aber ansonsten sehr gute Arbeit Razz
Ausserdem kann man die Floats kippen, das ist ein Relikt aus der Zeit, als die Rechnung noch 1/Blabla hiess. Da es jetzt 1000/Blabla heisst, kann man nun Ints verwenden.
Das sollte auch einen ziemlichen Geschwindigkeitsschub geben, da Berechnunge mit Floats (meines Wissens nach) langsamer sind als dieselben mit Integers.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Matthias

BeitragSo, Dez 09, 2007 19:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok. Das mit den Rändern habe ich beseitigt, aber das mit dem Schwarzen Punkt in der Mitte keine Ahnung das bekomme ich nicht weg.
Wobei es bei deinem Beispiel aber auch nicht anders war.

Habe den Code Editirt.

Vieleicht schafst du es ja noch wäre sehr interessant.

Achja das stimmt ints sind mit abstand die schnellsten. Aber noch schneller sind die Shl Shr Berfehle. Allerdings kann mann mit diesen nur in 2er Potenzen Multipliezieren oder Subtrahieren.

Noobody

BeitragSo, Dez 09, 2007 20:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, das war noch ein kleiner Fehler in meinem Code Wink
Einfach den Part "Value# = Treshold" durch "Value# = 1000" ersetzen.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSo, Dez 09, 2007 21:38
Antworten mit Zitat
Benutzer-Profile anzeigen
So, ich habe mal eine Variante mit 3D gemacht. Bei dieser Variante ist es nahezu egal, wieviele Objekte da rumschwirren. Der Schwellwert wird mittels TextureBlend 4 eingestellt. Allerdings müsste man, um es richtig zu machen, jeweils positive und negative einzelnd auf eine Texture (mit unterschiedlichen Helligkeitstönen) rendern und jeweils einzelnd ein TextureBlend 4 anwenden. Diese beide Texturen müssten dann anschliessend wieder zusammen gemischt werden. Ich habe es mir einfacher gemacht und das ganze in einem Rutsch per textureBlend gemacht. Der Nachteil dabei ist, dass der ''Metaballeffekt'' bei einzelnen Objetkten nicht auftritt, sondern erst ab so 500 Objekten.

Vielleicht nutzt es denoch den einen oder anderen

http://www.hectic.de/data/metaballs.rar
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D

Noobody

BeitragSo, Dez 09, 2007 21:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Wieder einmal überwältigend Razz
Der Metaballeffekt geht zwar verloren, aber dafür gehst du schon einen Schritt weiter. Ich hatte nämlich im Hinterkopf, mithilfe der Metaball - Berechnung diffuse Dinge wie z.B. Nebel in 3D darzustellen.
Statt ein Pixel zu zeichnen, wenn die Ladung an einem Ort einen Schwellenwert übersteigt, die Ladung als Alphawert nehmen und dieses auf ein Sprite rendern.
Dein Code erledigt genau das.

Ich überlege mir gerade, die Metaballs in 3D mit Kugeln darzustellen.
Aber der Knackpunkt, an dem ich mir die Zähne ausbeisse, ist, dass man nicht mehr einfach Pixel einzeichnen kann, sondern Vertices setzen muss und diese nachher vernünftig miteinander verbindet.
Hat jemand einen Denkansatz, wie ich das lösen könnte?
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Dreamora

BeitragSo, Dez 09, 2007 22:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Marching Cube / Marching Tetrahedron sind da der Ansatz.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Noobody

BeitragSo, Dez 09, 2007 22:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Ah danke.
Ich hatte da glaub auf Wikipedia auch was drüber gelesen in dem Zusammenhang.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Matthias

BeitragMo, Dez 10, 2007 11:15
Antworten mit Zitat
Benutzer-Profile anzeigen
@hectic.
Abzulut genial.

Ich suche auch schon seit einiger Zeit Woken zu erzeugen die realistich aussehen aber denoch wenig CPU Leistung verbraucht.

hectic

Sieger des IS Talentwettbewerb 2006

BeitragMo, Dez 10, 2007 12:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke erstmal.

Wenig CPU-Leistung verbrät die Funktion ja nun nicht (auf meinem System zumindest, scheint aber auch ein Grafikkartenproblem zu sein, wie auch Escape3D bei mir nur schlecht bis garnicht funktioniert). Wie das ganze abläuft, sieht man am besten, wenn man folgende Zeilen im Code auskommentiert:

Code: [AUSKLAPPEN]
;   CopyRect 0,0,512,512,0,0,BackBuffer(),TextureBuffer(Texture)
;   
;   ShowEntity Blending
;   RenderWorld


Der Rest des Effektes kommt eben durch das TextureBlend =4 welches über die ganze Scene gelegt wird.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D

BladeRunner

Moderator

BeitragMo, Dez 10, 2007 19:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Da mich das Thema spontan interessiert hat, hier mal meine kleine Interpretation des Ganzen.
https://www.blitzforum.de/upload/file.php?id=2458
Ist eine BMax-exe. Die Zahl links oben sind nicht die FPS, sondern die grade aktiven Metaballs.
Ich hoffe es gefällt Smile

EDIT: link aktualisiert.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
  • Zuletzt bearbeitet von BladeRunner am Mo, Dez 10, 2007 19:44, insgesamt einmal bearbeitet

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group