Seite 1 von 2

Pixel - Rate

Verfasst: 26.03.2005 20:27
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?

Verfasst: 26.03.2005 20:34
von Rubiko
kannst du "pixel effekt" noch genauer definieren?

Ja sicher (ich versuchs)

Verfasst: 26.03.2005 20:40
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.

Verfasst: 27.03.2005 00:23
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

Verfasst: 27.03.2005 00:42
von zigapeda
Ich glaube er hat gemeint das immer ein Pixel rot wird ähnlich wie bei Powerpoint überblendeffekte.

Verfasst: 27.03.2005 00:45
von vonTurnundTaxis
@AndyX:
Bevor du etwas postest solltest du deine Codes mal testen.
Der funktioniert nicht!

Verfasst: 27.03.2005 11:33
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 

Super danke

Verfasst: 27.03.2005 13:06
von Green Snake
Super danke

hat geklappt

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

trotzdem vilen dank euch allen

Verfasst: 27.03.2005 13:19
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.

Verfasst: 27.03.2005 13:47
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.