Pixel - Rate

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Green Snake
Beiträge: 1394
Registriert: 22.02.2005 19:08

Pixel - Rate

Beitrag von Green Snake »

hallo

habe eine grafische frage

weis jemand, wie man folgendes hinbekommt?

also ich habe einen schwarzen bildschirm (openscreen())
jetzt will ich, das der bildschirmm ganz rot wirt (RGB 255,0,0)
das sol aber nicht einfach so geschehen, sonder mit pixel effekt.
dh. es soll auf dem schwarzen bildschirm immer ein rotes pixel mehr zu sehen sein. dass sollte schnell gehen, so das in etwa 10 der ganze schirm rrot ist

wie mache ich dass?
-.-"
Benutzeravatar
Rubiko
Beiträge: 943
Registriert: 25.02.2005 19:43
Computerausstattung: Intel i7 2600k
8GB Ram
GeForce GTX 560 Ti
Wohnort: Schwabach

Beitrag von Rubiko »

kannst du "pixel effekt" noch genauer definieren?
Ich wollte die Welt verändern, doch Gott gab mir nicht den Quelltext.
Benutzeravatar
Green Snake
Beiträge: 1394
Registriert: 22.02.2005 19:08

Ja sicher (ich versuchs)

Beitrag von Green Snake »

Also ich meine, es sollte jede milli sekunde ein pixel (oder plot)
auf einer zufalls position auf dem screen erscheinen.
dies geht so lange, bis der screen ganz rot ist. wie mache ich das?

hoffe do / Ihrr hab das verstanden.
-.-"
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Beitrag von AndyX »

Code: Alles auswählen

for i = 0 to 255
clearscreen(0,0,0)
startdrawing(screenoutput())
plot(random(breite_von_screen),random(höhe_von_screen),rgb(i,0,0))
stopdrawing()
flipbuffers()
next i
Sollte so gehen.

Mfg,
AndyX
Benutzeravatar
zigapeda
Beiträge: 1753
Registriert: 06.03.2005 17:22
Wohnort: Kaufbeuren
Kontaktdaten:

Beitrag von zigapeda »

Ich glaube er hat gemeint das immer ein Pixel rot wird ähnlich wie bei Powerpoint überblendeffekte.
Benutzeravatar
vonTurnundTaxis
Beiträge: 2130
Registriert: 06.10.2004 20:38
Wohnort: Bayreuth
Kontaktdaten:

Beitrag von vonTurnundTaxis »

@AndyX:
Bevor du etwas postest solltest du deine Codes mal testen.
Der funktioniert nicht!
Nicht durch Zorn, sondern durch Lachen tötet man
ClipGrab | Pastor - jetzt mit kurzen URLs!
Icke
Beiträge: 143
Registriert: 08.09.2004 13:19

Beitrag von Icke »

Um den Screen zu füllen sollte man größere Flächen nehmen, z.B. Box. Um es dann ähnlich aussehen zu lassen wie bei PP müsste man dann widerum die bereits gesetzten Boxes nicht noch einmal setzen lassen. Am besten den Screen in Blöcke unterteilen.

Nicht das was gefordert, aber kleiner Ansatz :

Code: Alles auswählen




Width=640 
Height=480 

If OpenWindow(0, 0, 0, Width, Height, #PB_Window_SystemMenu|#PB_Window_ScreenCentered, "") 
  If StartDrawing(WindowOutput()) 
    
    Repeat
      
      EventID = WindowEvent()
      Box(Random(Width),Random(Height), 20,20 ,RGB(i,0,0)) 
      Delay(1)

      If EventID = #PB_EventCloseWindow
        quit=1
      EndIf
      
      If zaehler=1000
        quit=1
      Else
        zaehler+1
      EndIf
       
    Until quit=1
    
    StopDrawing()
    
    MessageRequester("",Str(zaehler)+" mal gezeichnet")
    
  EndIf 
   
EndIf 
Benutzeravatar
Green Snake
Beiträge: 1394
Registriert: 22.02.2005 19:08

Super danke

Beitrag von Green Snake »

Super danke

hat geklappt

(hatte zwar nicht genau das gemeint, konnte den code aber umschreiben)

trotzdem vilen dank euch allen
-.-"
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

@Icke
schon mal guter Ansatz
> Um den Screen zu füllen sollte man größere Flächen nehmen, z.B. Box.
siehe B)
> ...dann widerum die bereits gesetzten Boxes nicht noch einmal setzen lassen.
siehe C)

ausserdem hast du durch das zeichnen aufs Fenster das Problem A) umgangen :allright:

Two-Picture-Fade

A) das erste Problem:
Die Screen-Buffer

durch das Double-Buffering ist es nicht möglich, auf bereits vorhandenes zu zeichnen,
da zwei Buffer existieren.
wenn wir jetzt in jedem frame ein neues Pixel setzen,
wird in jedem der zwei Screenbuffer nur die Hälfte der Informationen stehen.

also brauchen wir einen extra-Buffer (ein Sprite) in den wir zeichnen,
und der in jedem Frame angezeigt wird.


B) das zweite Problem:
Die Framerate

wenn wir in jedem Frame ein Pixel verändern, brauchen wir für einen 800x600 Screen
480000 Frames, bei 60FPS sind das 8000 Sekunden oder 2:13:20
auf einem TFT oder LCD können wir (bei manchen) die Framerate extrem pushen,
und ohne V-Sync Flippen, aber bei vielen Monitoren geht das nicht,
ich habe das in meinem Beispiel mal gemacht,
aber ich bräuchte Hilfe (hallo Danilo :wink: oder wer immer sich damit auskennt),
um das Buffer-Drawing und das Screen-Drawing zeitlich zu trennen, z.b. durch Threads


mir ging es hauptsächlich um den Algorythmus, und damit zu

C) das dritte Problem:
Der Algorythmus

wenn wir die Pixel per Zufall auswählen,
dann werden bereits gesetzte Pixel erneut gezeichnet,
je weiter der Prozess fortgeschritten ist, umso mehr.
also brauchen wir einen algorythmus,
mit dem jedes pixel genau einmal gezeichnet wird.

Die Lösung hier stammt aus den 80er Jahren und wurde für den C64 veröffentlicht.

allerdings wurde das damals auf dem Textbildschirm mit 40*25 Zeichen gemacht,
also ging es um 1000 Punkte, nicht um 480000, aber das Prinzip ist das gleiche.

normalerweise überträgt man Daten,
indem man einen Zähler immer um 1 hochsetzt.
man kann auch um andere werte hochsetzen,
und am Ende des Buffers um die Bufferlänge runtersetzen,
dann wird "streifenweise" übertragen.
um wirklich jede Speicherstelle zu erreichen,
muss man ungerade Schrittweiten nehmen.
(mit geraden würde es zu überschneidungen kommen)
das löse ich dadurch, daß ich aus einem angegebenen Mode
eine ungerade Zahl für die Schrittweite erzeuge,
aus 0 wird 1, aus 1 wird 3, aus 2 wird 5, usw.

für die meisten Schrittweiten sieht die Übertragung sehr regelmäßig aus,
aber ein paar werte erzeugen scheinbar zufällige Muster.
leider weiss ich nicht mehr, in welchem Verhältnis diese Schrittweiten
zur Buffergröße standen, also müssen wir rumprobieren,
im vorliegenden Beispiel hab ich einfach mal eine willkürliche Zahl genommen,
leider ist das Ergebnis immer noch ziemlich regelmäßig.
aber es gibt Werte, mit denen es 'gut' aussieht, glaubt mir ;)


ausserdem arbeite ich mit der überblendung von einem sprite zu einem anderen,
eine überblendung von einem rein schwarzen zu einem rein roten Screen
erscheint mir etwas 'anwendungsarm'

so, hier nun der

Code: Alles auswählen

#ScrW = 800
#ScrH = 600

InitSprite()
InitKeyboard()

OpenScreen( #ScrW, #ScrH,32,"Test")

; ich Create mal alle 3 verwendeten Sprites vorab,
; damit man sieht, welche nummern ich verwende...

CreateSprite(8000, #ScrW, #ScrH)    ; Ursprung
CreateSprite(8001, #ScrW, #ScrH)    ; Ziel
CreateSprite(8002, #ScrW, #ScrH)    ; Angezeigter Blendzustand

; ***************** Anfang Demo-Sprites Erzeugung

; ich grabbe hier mal irgendwas,
; man kann auch beliebige Grafix laden,
; (bitte auf exaktes format achten...)
; oder den vorher dargestellten Screen
; in Sprite 8000 grabben....

; einfach ein buntiges Bildchen für Sprite 8000
ClearScreen(0,0,0)
StartDrawing(ScreenOutput())
For n=0 To 999
    Circle(Random(#ScrW),Random(#ScrH),4+Random(28),RGB(130+Random(120),130+Random(120),130+Random(120)))
Next
StopDrawing()

FlipBuffers()
Repeat:ExamineKeyboard():Until KeyboardPushed(#PB_Key_All)    ; einfach mal schauen, wie's aussieht
FlipBuffers()

GrabSprite(8000, 0, 0, #ScrW, #ScrH)

; und nen rein roten Screen für 8001
ClearScreen(255,0,0)
GrabSprite(8001, 0, 0, #ScrW, #ScrH)
ClearScreen(0,0,0)

; ***************** Ende Demo-Sprites Erzeugung


; *** die Argumente für die Routine

; der Blendmode bestimmt das relative Pixel-Offset (Schrittweite der Überblendung)
; erlaubt sind alle Werte von 0 bis zur Hälfte der Pixel-Anzahl

BlendMode = 126845

; Die Festlegung der Blendtime ist notwendig, um die adäquate Framerate zu berechnen
; Angabe in Sekunden

BlendTime = 10

; ****
; **** Die Eigentliche Routine
; ****

AnzPix.l = #ScrW * #ScrH  ; Gesamtanzahl der vorhandenen Pixel

Nxt.l = BlendMode*2+1
; aus dem Mode wird eine ungerade Zahl gemacht
; für die Schrittweite der Überblendung

If Nxt > AnzPix Or Nxt < 0 : End : EndIf   ; Abbruch, wenn die Schrittweite größer als der Screen ist.

ActPix.l = 0    ; aktuelles Pixel, das übertragen wird.

FrmRt = AnzPix / BlendTime  ; VORSICHT: dreckige Lösung
SetFrameRate(FrmRt)         ; die Framerate wird hochgepusht

CopySprite(8000,8002)
DisplaySprite(8002,0,0)
FlipBuffers(0)

count = 1
Repeat

    PixY = ActPix/#ScrW
    PixX = ActPix-PixY*#ScrW

    UseBuffer(8002)                     ; in Sprite 8002 ausgeben
    ClipSprite(8001, PixX, PixY, 1, 1)  ; nur das aktuelle Pixel
    DisplaySprite(8001, PixX, PixY)     ; in den Blend-Buffer übertragen
    UseBuffer(-1)                       ; wieder auf Screen ausgeben

    ActPix + Nxt            ; Pixel-Offset dazuaddieren
    If ActPix >= AnzPix     ; innerhalb des Bereichs halten
        ActPix - AnzPix
    EndIf

    DisplaySprite(8002,0,0) ; aktuellen Blend-Buffer anzeigen
    FlipBuffers(0)          ; OHNE V-SYNC flippen !

    count+1
    ExamineKeyboard()

Until count >= AnzPix Or KeyboardPushed(1)

Repeat:ExamineKeyboard():Until KeyboardPushed(#PB_Key_All)    ; und nochmal auf taste warten
Taste drücken zum Starten,
am Ende nochmal Taste drücken.

der Vorgang kann mit ESC abgebrochen werden.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

so, nochmal Danke an Icke

ich hab jetzt mein prog mal umgestrickt auf direktes plotten ins Window,

damit wird das Screen-Problem (Buffer & Framerate) umgangen,
ausserdem kann man auf allen Monitoren den Effekt beobachten...

...spielt mal mit dem Wert für BlendMode herum ;)
gibt schicke Effekte

Code: Alles auswählen

#ScrW = 800
#ScrH = 600

OpenWindow(1,0,0,#ScrW, #ScrH,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Test")

; einfach ein buntiges Bildchen für den Window-Background

StartDrawing(WindowOutput())
For n=0 To 999
    Circle(Random(#ScrW),Random(#ScrH),4+Random(28),RGB(130+Random(120),130+Random(120),130+Random(120)))
Next
StopDrawing()

Delay(2000)
;ich war zu blöd und zu faul, auf ne taste zu warten ;)

; *** die Argumente für die Routine

; der Blendmode bestimmt das relative Pixel-Offset (Schrittweite der Überblendung)
; erlaubt sind alle Werte von 0 bis zur Hälfte der Pixel-Anzahl

BlendMode = 126845

; ****
; **** Die Eigentliche Routine
; ****

AnzPix.l = #ScrW * #ScrH  ; Gesamtanzahl der vorhandenen Pixel

Nxt.l = BlendMode*2+1
; aus dem Mode wird eine ungerade Zahl gemacht
; für die Schrittweite der Überblendung

If Nxt > AnzPix Or Nxt < 0 : End : EndIf   ; Abbruch, wenn die Schrittweite größer als der Screen ist.

ActPix.l = 0    ; aktuelles Pixel, das übertragen wird.

count = 1
StartDrawing(WindowOutput())
FrontColor(255,0,0)
Repeat

If count < AnzPix

    PixY = ActPix/#ScrW
    PixX = ActPix-PixY*#ScrW
    Plot(PixX,PixY)
  
    ActPix + Nxt            ; Pixel-Offset dazuaddieren
    If ActPix >= AnzPix     ; innerhalb des Bereichs halten
        ActPix - AnzPix
    EndIf

    count +1
EndIf

Until WindowEvent() = #PB_Event_CloseWindow
[EDIT]
Shit, ich merke grad, nicht alle Werte für BlendMode Funktionieren.
und zwar solche, die einen ganzzahligen Teiler für AnzPix ergeben.
...hmmm da war doch noch irgendwas getrickst bei dem 20 jahre alten algo...
ich hab halt die hefte nicht mehr, das ist alles aus der Erinnerung...

[EDIT2]
hm... also, werte, die funktionieren, machen auch einen guten eindruck..
z.b. 3 oder 5 oder 6
liegt wahrscheinlich auch daran, dass bei der menge der pixel und dem tempo
die regelmässigkeit garnicht so auffällt.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten