Bild in der Gui zeichnen zum späteren nutzen

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

 

funkheld

Betreff: Bild in der Gui zeichnen zum späteren nutzen

BeitragSo, Aug 21, 2016 19:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo, guten Tag.
Ich hab eine Gui in der ich ein Rechteck brauche , welches ich dann hier drin : Case EVENT_GADGETPAINT
benutzen möchte. Dieses Rechteck möchte ich in dem gleichen Programm anfertigen. Möchte aber dieses :
Case EVENT_GADGETPAINT damit nicht belasten , weil es ja dann immer dort drin steht obwohl ich es nur einmal brauche.
Ich habe jetzt einfach dieses aufgemacht : Graphics 600,400 darin gezeichnet und benutze jetzt das Rechteck in der Gui. Nur wie kann ich dieses Fenster dann wieder schließen?

Oder gibt es eine andere Möglichkeit? Ich möchte aber kein Bild von der Platte einladen.

Danke.
Gruss

Code: [AUSKLAPPEN]

Strict

Import MaxGUI.Drivers

Graphics 600,400
Global bild:TImage=CreateImage(60,40)
SetColor 0,0,255
DrawRect 0,0,70,40
SetColor 255,255,255
GrabImage bild,0,0
cls

global text:string
global rot:float
global xs:float,ys:float

Global Window:TGadget=CreateWindow("esp-filemap",180,20,1100,600)

Global vor:Tgadget=CreateButton("vor",90,15,40,25,Window)
Global links:Tgadget=CreateButton("links",10,40,40,25,Window)
Global hlinks:Tgadget=CreateButton("hli",50,40,40,25,Window)
Global mitte:Tgadget=CreateButton("mitte",90,40,40,25,Window)
Global hrechts:Tgadget=CreateButton("hre",130,40,40,25,Window)
Global rechts:Tgadget=CreateButton("rechts",170,40,40,25,Window)
Global zur:Tgadget=CreateButton("zur",90,65,40,25,Window)
Global radar1:Tgadget=CreateButton("radar1",90,100,40,25,Window)
Global radar2:Tgadget=CreateButton("radar2",130,100,40,25,Window)
Global v0:Tgadget=CreateButton("v0",190,100,40,25,Window)
Global v1:Tgadget=CreateButton("v1",190,125,40,25,Window)
Global v2:Tgadget=CreateButton("v2",190,150,40,25,Window)
Global killer:Tgadget=CreateButton("cls",377,20,40,25,Window)

Global text_g:TGadget = CreateTextArea( 270, 20, 100,400, window )
global nmap_edit:Tgadget = CreateCanvas(460,20,500,500,window)
ActivateGadget(nmap_edit)

Local MyTimer:Int = MilliSecs()
Local ZweiterTimer:Int = Millisecs()

xs=200
ys=200

CreateTimer(60)
Repeat
   Local tmpGadget:Tgadget
   
   If MilliSecs() - MyTimer >= 400 Then 
     MyTimer = MilliSecs()
   endif

   If MilliSecs() - ZweiterTimer >= 1000 Then       
     ZweiterTimer = MilliSecs()
   EndIf

   Select TGadget(EventSource())
      Case vor
     case links
     case hlinks
     case mitte
     case hrechts
     case rechts
     case zur   
     case radar1
     case radar2
     case v0
     case v1
     case v2
     Case killer
        SetGadgetText text_g, ""
       text=""
    End Select
   
   Select WaitEvent()
      Case EVENT_GADGETSELECT
        tmpGadget = TGadget(EventSource())
     
      Case EVENT_GADGETACTION
        tmpGadget = TGadget(EventSource())

      Case EVENT_GADGETACTION
        tmpGadget = TGadget(EventSource())

      Case EVENT_TIMERTICK
        tmpGadget = TGadget(EventSource()) 
        redrawGadget (nmap_edit)
 
      Case EVENT_GADGETPAINT
         tmpGadget = TGadget(EventSource())
         SetGraphics (CanvasGraphics(nmap_edit))
         cls
         SetRotation rot
         SetImageHandle(bild,30,20)
           DrawImage bild,xs,ys
 
             Flip

      Case EVENT_MOUSEDOWN
        tmpGadget = TGadget(EventSource())
     
      Case EVENT_MOUSEMOVE
        tmpGadget = TGadget(EventSource())
 
      Case EVENT_MOUSEUP
        tmpGadget = TGadget(EventSource())
     
      Case EVENT_WINDOWCLOSE
        tmpGadget = TGadget(EventSource())
        end   

      Case EVENT_APPTERMINATE
        tmpGadget = TGadget(EventSource())
        End
         
      Case EVENT_MENUACTION
        tmpGadget = TGadget(EventSource())   
   End Select
Forever

BladeRunner

Moderator

BeitragSo, Aug 21, 2016 21:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Doch, Event_Gadgetpaint ist exakt der passende Ort dafür.
Alles was eingezeichnet werden soll gehört dorthin. Belastend ist das auch nur sehr begrenzt. Moderne Grafikkarten erledigen das im vorbeigehen, ist nicht wie beim VIC wo jeder Pixel zählte.
Mit irgendwelchen Tricksereien wegen eines Rechteckes anzufangen wird mehr Prozessorleistung verschlingen als es auf der GPU einspart.
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
 

funkheld

BeitragSo, Aug 21, 2016 22:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe das jetzt als einmalige Abfrage gemacht , danach wird z=1 und wird nicht mehr durchlaufen.

Code: [AUSKLAPPEN]

 Case EVENT_GADGETPAINT
         tmpGadget = TGadget(EventSource())
         SetGraphics (CanvasGraphics(nmap_edit))
         if z=0 then
           setcolor 255,0,0
           DrawRect 0,0,50,30
           GrabImage auto,0,0
           SetColor 255,255,255
           cls
           z=1
        endif

         cls
         SetRotation rot+radd
         SetImageHandle(auto,25,15)
         DrawImage auto,xs,ys
         Flip

BladeRunner

Moderator

BeitragMo, Aug 22, 2016 5:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Und wo siehst du die Zeit Ersparnis oder den Vorteil darin statt eines Rechtecks ein Bild ein zu zeichnen?
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
 

funkheld

BeitragMo, Aug 22, 2016 8:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich Zeichne ein Bild welches ich dann in eine Image kopiere. Ich benutze nicht das Rechteck direkt.

Gruss

Midimaster

BeitragMo, Aug 22, 2016 10:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Absolut sinnvolle Technik! Zwar mag das bei einem einzigen roten Rechteck noch keinen Sinn geben, aber wenn man z.B. aufwendige (errechnete) Hintergrundbilder darstellen will, ist es durchaus sinnvoll sie einmal zu malen und später als Image im Spiel zu verwenden.
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

BladeRunner

Moderator

BeitragMo, Aug 22, 2016 10:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Einspruch!
Da wäre in der Tat sinnvoll, wenn er deutlich (und zwar wirklich deutlich) mehr als ein Rechteck einrendern wollte. Ein Beispiel wären zB größere Mengen Text. Dann würde es an dem Flaschenhals RAM->GPU eng werden.
Und selbst dann sind wir hier bei einem Stück Anwendungssoftware wo es nicht darauf ankommt 120FPS zu generieren.

Ein einzelnes, profanes Rechteck hechelt aber selbst die letzte OnBoard-Grafikgurke mit links weg, die sind darauf optimiert einige hundert Millionen Pixel pro Sekunde einzurendern, und die Befehlsfolge zum Rendern des Rechteckes liegt bei einigen Byte Größe.
Daher ist hier ein Image weit over the Top, es bringt keinen Vorteil und bläst nur unnötig den Code auf. Nichts gegen Optimierungen, aber doch dort wo sie wirklich sinnvoll oder nötig sind.
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
 

funkheld

BeitragMo, Aug 22, 2016 11:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Es ist nur ein Test , ob es sinnvoll funktionieren kann. Danach wird es ausgebaut.

Da kommt noch viel mehr Grafik und Text hin , welche gebraucht wird.

Danke.
Gruss

BladeRunner

Moderator

BeitragMo, Aug 22, 2016 21:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Nur mal so als Überblick wieviel da gezeichnet werden muss, damit es sich lohnt Umwege zu gehen:
BlitzMax: [AUSKLAPPEN]
Graphics 640 , 400

Repeat
Cls
start=MilliSecs()
For i = 1 To 10
coords.add(Rnd(640),Rnd(400),Rnd(640),Rnd(400))
Next
coords.draw()
SetColor 255,0,0
DrawText String(coords.count() ) , 0 , 0
DrawText String( (MilliSecs() - start) ) , 600 , 0
If (MilliSecs() - start) > 17 Then
count:+ 1
If count > 10 Then
RuntimeError("FPS<60 bei "+coords.count()+ "Rechtecken")
EndIf
EndIf

Flip
Until KeyHit (key_escape)

Type coords
Global list:TList = New TList

Field x:Int , y:Int , w:Int , h:Int

Function add(xx:Int , yy:Int , ww:Int , hh:Int)
Local c:coords = New coords
c.x = xx
c.y = yy
c.w = ww
c.h = hh
list.addlast(c)
End Function

Function draw()
For Local c:coords = EachIn coords.list
SetColor Rnd(255),Rnd(255),Rnd(255)
DrawRect c.x , c.y , c.w , c.h
Next
End Function

Function count:Int()
Return list.count()
End Function
End Type

Dieser kleine Testcode macht nichts anderes als Rechtecke an zufälligen Positionen zu erstellen, in einer Liste zu speichern und diese Liste dann abzuarbeiten und einzuzeichnen. In jedem Frame kommen 10 neue Rechtecke dazu.
Dann ermittelt das Programm wie lange es dauert die Hauptschleife zu durchlaufen, dauert ein durchlauf mehr als 17 Millisekunden (und liegt damit über der Zeit die benötigt wäre um 60 Frames pro Sekunde zu rendern) wird ein Counter erhöht. Das wird gemacht weil es durchaus mal durch andere Prozesse zu kleinen Schwankungen in der Geschwindigkeit kommen kann. Wird zum zehnten Mal der Grenzwert überschritten, bricht das Programm ab und teilt mit wieviele Rechtecke gerendert wurden bevor es zu langsam wurde.

Das Ergebnis bei meinem Rechner:

ca. 5500 Rechtecke im Debug-Modus und fast genau 15000 im Release-Modus.
Ab da ist also soviel Dampf auf der GPU dass es sinnvoll wird sie zu entlasten weil eventuell sichtbare Verzögerungen auftreten können.

Bei Text ist es abhängig von der Anzahl der zu rendernden Buchstaben, stricke ich den Test auf Text um kann ich bei einem 5-Buchstaben-Text im Release-Modus knapp 7000 Instanzen rendern bevor es zu langsam wird, sprich gute 35000 Buchstaben.

Auf einen normalen Screen passen soviele Buchstaben und Rechtecke nicht drauf, bevor es also langsam wird ist der Platz zum Einzeichnen zu Ende.

Noch dazu wird man in einem GUI-getriebenen Programm idR. nicht viel Text in ein GrafikCanvas rendern.

Die Frage ob es einem was bringt ein Rechteck durch ein Bild zu ersetzen war eh schon hypothetisch, aber wie sich damit zeigt ist sie es in dem meisten Fällen in denen mehr zu ersetzen ist wohl auch.

Natürlich lässt der Test unberücksichtigt, dass das Programm selbst auch Zeit zur Ausführung benötigt, aber wenn es anfängt zu ruckeln würde ich dann auch eher dort nach Optimierungsmöglichkeiten suchen, und nicht an der grafischen Ausgabe.
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
 

funkheld

BeitragMo, Aug 22, 2016 22:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Ein überzeugender Test mit der Grafik.
Da erkennt man auch wie Leistungsfähig dieses BlitzMax ist.

Es ist nicht so schnell in die Knie zu zwingen.

Danke.
Gruss

BladeRunner

Moderator

BeitragDi, Aug 23, 2016 9:01
Antworten mit Zitat
Benutzer-Profile anzeigen
Der limitierende Faktor ist da weniger die Sprache, das sind Hardwaregrenzen.
Aber BMax generiert schon sehr brauchbaren Maschinencode.
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

Midimaster

BeitragDi, Aug 23, 2016 9:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Es geht doch nicht darum wieviele Rechtecke man zeichnen kann, bevor die Grafikkarte in die Knie geht. Es geht doch vielmehr darum, wieviele Rechtecke man zeichnen kann, bevor ein DrawImage() schneller wäre. Und selbst das wäre noch nicht Realitätsnah. Denn wollte man wirklich ein Bild mit Grafikbefehlen zeichnen kämen sicherlich auch viele DrawOval() und DrawPoly() vor. Ganz zu schweigen von den internen Rotationen, die dazu nötig wären.

hier mal eine Test mit 100 Grafikbefehlen:

BlitzMax: [AUSKLAPPEN]
Graphics 800,600
Global Bild:TImage=CreateImage(300,300)
Global Zeit1%, Zeit2%

DrawMyImage
GrabImage Bild,0,0

Repeat
Cls
Zeit1=MilliSecs()
For i=0 To 10
'SetHandle -400,-300
DrawMyImage
Next
Zeit1=MilliSecs()-Zeit1
SetColor 255,255,255
SetRotation 0
Zeit2=MilliSecs()
For i=0 To 10
DrawImage bild, 400,300
Next
Zeit2=MilliSecs()-Zeit2
Print "Zeitvegleich:" + zeit1 + " " + Zeit2
Flip 0
Until KeyHit(KEY_ESCAPE)

SetColor 255,255,255
Repeat
Cls
Print zeit
Flip
Until KeyHit(KEY_ESCAPE)



Function DrawMyImage()
SeedRnd 12345
For Local i%=0 To 100
SetColor Rand(255),Rand(255),Rand(255)
SetRotation i
Select Rand(3)
Case 0
DrawRect 50,50,Rand(50),Rand(50)
Case 1
DrawOval 50,50,Rand(50),Rand(50)
Case 2
DrawLine 50,50,Rand(50),Rand(50)
End Select
Next
End Function


Dabei ist jetzt auch noch außer Acht gelassen, das das gemalte Objekt sich insgesamt bewegen müßte, was ein SETHANDLE() nötig macht. Und das Gesamtobjekt könnte eine insgesamte Drehung machen, was mit den bereits für das Zeichnen benötigten SETROTATION() zu einer doppelten Drehung mit verschiedenen Ursprüngen führt.

In meinem Testaufbau überholt das vorgerenderte Bild bereits bei 10 Zeichenbefehlen das live gerenderte.
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

BladeRunner

Moderator

BeitragDi, Aug 23, 2016 9:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Sicher wird das gerenderte Bild weit früher performanter sein, das bestreitet niemand. ABER: Eine Codeoptimierung um der Optimierung willen ist doch nicht zielführend. Wenn mein Code stabil und performant läuft muss ich ja nicht auf Teufel komm raus optimieren, und bis er imperformant wird hab ich eine Menge Spielraum.
Für 99% der UseCases ist diese Optimierung nicht nötig, da der 'unoptimierte' Code weder den Prozessor noch die GPU in Bedrängnis bringen wird.
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

Midimaster

BeitragDi, Aug 23, 2016 10:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, wenn Du eine Optimierung für nicht notwendig hältst, bloß weil der Code auf Deinem Rechner schnell ist....

Wenn ich Deinen Test auf meinem Athlon durchführe bricht er genau nach 830 Rechtecken ab. Auf dem Atom habe ich es noch gar nicht getestet... Du ahnst gar nicht, wieviele Rechner "da draußen" sind, die noch schlechtere Ergebnisse liefern. Wenn Du Software für "jedermann" erstellen willst, musst Du schon darauf achten, dass sie auf möglichst vielen Rechnern flüssig läuft.

Solange Du Software immer nur für Dich selber programmierst, hast Du sogar zu 100% Recht!
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

BladeRunner

Moderator

BeitragDi, Aug 23, 2016 11:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, das aktuelle Projekt sieht doch sehr homegrewn aus. Und 830 Rechtecke sind immer noch mehr als ich bei einem normalen UseCase erwarten würde - was soll denn da alles eingezeichnet werden?
Wenn ich von einer grafiklastigen Geschichte ausgehe werde ich auch diesen Fall berücksichtigen, aber ein Anwendungsprogramm welches die Sensordaten eines Roboters auswertet wird in der Regel wohl nicht Multilayergrafiken benötigen. Die Sensordaten kommen, wie in anderen Threads zu lesen alle 400ms rein, also warum soll ich hier dann so einen Aufwand betreiben?
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

Cykid

BeitragDi, Aug 23, 2016 13:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Man kann ja optimieren was eben geht aber man muss dabei immer den kosten / Nutzen Faktor im Blick haben.

Wenn ich weiß das da niemals mehr als 10 Rechtecke auftauchen, kann ich mir die liebe müh sparen.

Ist mein Programm so geschrieben das Theoretisch Tausende auftauchen können, sollte ich das ganze so weit optimieren wie es mir möglich ist.

Und das "optimiert" lernen zu wollen ist ja erstmal nicht verwerflich und wenn man es eben machen möchte, um es mal gemacht zu haben, ist doch alles gut =)

BladeRunner

Moderator

BeitragDi, Aug 23, 2016 15:47
Antworten mit Zitat
Benutzer-Profile anzeigen
Dagegen sagt ja niemand was - ich sehe nur im aktuellen Fall wirklich keinerlei Bedarf für derartige Spielchen. Eigentlich ist auch diese Diskussion jenseits jedes Kosten-Nutzen-Verhältnisses Wink
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

DAK

BeitragMi, Aug 24, 2016 19:41
Antworten mit Zitat
Benutzer-Profile anzeigen
In diesem Fall tät ich weniger auf die Performance schauen als auf die anderen möglichen Nutzen.

Performance ist, wie schon erörtert, hier recht wurscht. Egal ob das jetzt ein paar Rechtecke oder ein paar Bilder sind, jeder Rechner aus diesem Jahrzehnt wird das locker packen, so wie auch die Meisten aus dem letzten Jahrzehnt.

Wichtiger wäre hier:
-) Wird dadurch der Code les- und damit wartbarer?
-) Wird der Code dadurch flexibler?

Möchte man z.B. später ein echtes Bild reinladen (z.B. einen schönen Button als PNG), dann zahlt sich das schon aus.

Wenn nicht, dann ist das auch nicht nötig.
Gewinner der 6. und der 68. BlitzCodeCompo

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group