syncronisieren von/mit Window Redraw
syncronisieren von/mit Window Redraw
Folgendes Problem:
Ich möchte ein Spiel auf ein Window rendern. Dazu verwende ich zum einen DirectX zum anderen möchte ich aber auch einen Softwarerenderer auf Basis der Image-Lib und 2DDrawing-Lib anbieten. Das funktioniert auch dank dem neuen Image Alphachannel recht einfach. Nur ist es so das das Zeichnen auf das Fenster im Softwarerenderer nicht mit dem Redraw des Fensters syncron ist. Dadurch entstehen sehr hässliche Tearing Effekte, die extrem auffallend sind, da der Hintergrund automatisch scrollt. Die exakt gleichen Effekte habe ich, wenn ich mit DirectX ohne VSync rendere, was dort kein Problem ist, da ich VSync mit DirectX ja nutzen kann.
Irgendwelche Ideen wie man dem Herr werden könnte?
Ich möchte ein Spiel auf ein Window rendern. Dazu verwende ich zum einen DirectX zum anderen möchte ich aber auch einen Softwarerenderer auf Basis der Image-Lib und 2DDrawing-Lib anbieten. Das funktioniert auch dank dem neuen Image Alphachannel recht einfach. Nur ist es so das das Zeichnen auf das Fenster im Softwarerenderer nicht mit dem Redraw des Fensters syncron ist. Dadurch entstehen sehr hässliche Tearing Effekte, die extrem auffallend sind, da der Hintergrund automatisch scrollt. Die exakt gleichen Effekte habe ich, wenn ich mit DirectX ohne VSync rendere, was dort kein Problem ist, da ich VSync mit DirectX ja nutzen kann.
Irgendwelche Ideen wie man dem Herr werden könnte?
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!

- coder
- Beiträge: 204
- Registriert: 25.09.2005 17:53
- Computerausstattung: Intel Core2Quad Q8200 @ 2.33GHz
ASUS P5Q3, 2GB DDR3-1066 RAM, ATi Raedeon HD 4850 - Wohnort: Deutschland
- Kontaktdaten:
Genau, du solltest nicht direkt auf das Fenster zeichnen, sondern erst auf ein Image und das dann aufs Windows drawn oder du nutzt ein ImageGadget dazu, was noch ein bisschen mehr Komfort bringt, da du dich dann nicht ums Redraw-Event kümmern musst...
Windows 7 x64 | PureBasic 4.60 4.50 4.02
Ja verdammt, meine Eltern wohnen immer noch bei mir!
Ja verdammt, meine Eltern wohnen immer noch bei mir!
- Fluid Byte
- Beiträge: 3110
- Registriert: 27.09.2006 22:06
- Wohnort: Berlin, Mitte
Wie bereits erwähnt lässt sich Doublebuffering bewerkstelligen wenn vor dem Anzeigen erst auf ein Image gezeichnet wird. Ich bin mir aber gerade nicht sicher ob das exakt ist was du meinst. Hier ein kleines Beispiel:
Code: Alles auswählen
Define Frames, Angle.f
OpenWindow(0,0,0,340,240,"void",#WS_SYSMENU | #WS_CAPTION | #WS_MINIMIZEBOX | 1)
ImageGadget(0,0,0,0,0,CreateImage(0,340,240))
AddWindowTimer(0,0,30)
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Timer
Angle + 0.05 : Frames + 1 : Radius = 80
BackColor = GetSysColor_(#COLOR_3DSHADOW)
; ---> DRAW BACKGROUND
StartDrawing(ImageOutput(0))
DrawingMode(1)
Box(0,0,350,250,BackColor)
For BX = 0 To 239 Step 2
Box(0,BX,338,1,RGB(135,135,135))
Next
; ---> DRAW CIRCLES #1
Ellipse(165,120,Abs((Cos(Angle - 1) * 30)),Abs((Cos(Angle) * 30)),0)
Ellipse(165,120,Abs((Cos(Angle - 1) * 30)) - 2,Abs((Cos(Angle) * 30)) - 2,RGB(100,220,50))
; ---> DRAW CIRCLES #2
For i=0 To 4
Ellipse(165 + (Sin(Angle + (1.25 * i)) * Radius),120 + (Cos(Angle+(1.25 * i)) * Radius),32,32,0)
Ellipse(165 + (Sin(Angle + (1.25 * i)) * Radius),120 + (Cos(Angle+(1.25 * i)) * Radius),30,30,$0090FF)
Next
; ---> DRAW CIRCLES #3
Ellipse(166,119 + (Cos(Angle) * 100),16,16,$0)
Ellipse(166,119 + (Cos(Angle) * 100),14,14,$FFFFFF)
Ellipse(166,119 + (-Cos(Angle) * 100),16,16,$0)
Ellipse(166,119 + (-Cos(Angle) * 100),14,14,$FFFFFF)
Ellipse(169 + (Cos(Angle) * 150),116,16,16,$0)
Ellipse(169 + (Cos(Angle) * 150),116,14,14,$FFFFFF)
Ellipse(169 + (-Cos(Angle) * 150),116,16,16,$0)
Ellipse(169 + (-Cos(Angle) * 150),116,14,14,$FFFFFF)
StopDrawing()
SetGadgetState(0,ImageID(0))
EndIf
Until EventID = #PB_Event_CloseWindowWindows 10 Pro, 64-Bit / Outtakes | Derek
-
Kaeru Gaman
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
ich hatte vor einiger Zeit mal ein kleines Beispiel für ein getimetes ImageGadget gepostet:
http://www.purebasic.fr/german/viewtopic.php?t=19394
je nach komplexität des Inhalts könnte es natürlich etwas eng werden mit dem timing.
http://www.purebasic.fr/german/viewtopic.php?t=19394
je nach komplexität des Inhalts könnte es natürlich etwas eng werden mit dem timing.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.
Doublebuffering verwende ich sowieso. Es kommt trotzdem zu Tearing, da das Zeichnen des Images nicht syncron läuft mit dem neuzeichnen des Fensters.
Das Problem ist es das Zeichnen des Sprites mit dem Redraw des Fensters zu syncronisieren oder eben umgekehrt.
Ich schau mir jetzt erstmal Kaeru Code an.
Das Problem ist es das Zeichnen des Sprites mit dem Redraw des Fensters zu syncronisieren oder eben umgekehrt.
Ich schau mir jetzt erstmal Kaeru Code an.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!

- Fluid Byte
- Beiträge: 3110
- Registriert: 27.09.2006 22:06
- Wohnort: Berlin, Mitte
Ich denke ein kleiner Beispielcode würde hier helfen dein Problem etwas besser zu verstehen.
Windows 10 Pro, 64-Bit / Outtakes | Derek
OKFluid Byte hat geschrieben:Ich denke ein kleiner Beispielcode würde hier helfen dein Problem etwas besser zu verstehen.
Dein Beispiel etwas umgebaut. Hier wird nun ein Foto hoch und runtergescrollt. Dabei entstehen Tearing Effekte wie Wellenbewegungen im Bild.
Das Foto kann hier runtergeladen werden: http://www.gametreasure.de/Temp/test.png
Code: Alles auswählen
Define.i YPos, YDirection
timeBeginPeriod_(1)
UsePNGImageDecoder()
LoadImage(5, "d:\test.png")
OpenWindow(0,0,0,1024,768,"void",#WS_SYSMENU | #WS_CAPTION | #WS_MINIMIZEBOX | 1)
ImageGadget(0,0,0,1024,768,CreateImage(0,1024,768))
AddWindowTimer(0,0,10)
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Timer
StartDrawing(ImageOutput(0))
Box(0,0,1024,768,0)
DrawImage(ImageID(5), 0, YPos)
StopDrawing()
If YPos < 1
YPos = 1
YDirection = 1
ElseIf YPos > 300
YPos = 300
YDirection = -1
Else
YPos + YDirection
EndIf
SetGadgetState(0,ImageID(0))
EndIf
Until EventID = #PB_Event_CloseWindow
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!

- Fluid Byte
- Beiträge: 3110
- Registriert: 27.09.2006 22:06
- Wohnort: Berlin, Mitte
Also ob nun dein Beispiel mit GDI oder per Screen
Macht bei mir keinen Unterschied. Es ruckelt ab und an aber kein Tearing.
Code: Alles auswählen
Define.i YPos, YDirection
InitSprite()
UsePNGImageDecoder()
OpenWindow(0,0,0,1024,768,"void",#WS_SYSMENU | #WS_CAPTION | #WS_MINIMIZEBOX | 1)
OpenWindowedScreen(WindowID(0),0,0,1024,768,0,0,0)
LoadSprite(0,"test.png")
Repeat
EventID = WindowEvent()
ClearScreen(0)
If YPos < 1
YPos = 1
YDirection = 1
ElseIf YPos > 300
YPos = 300
YDirection = -1
Else
YPos + YDirection
EndIf
DisplaySprite(0,0,YPos)
FlipBuffers()
Until EventID = #PB_Event_CloseWindow Windows 10 Pro, 64-Bit / Outtakes | Derek
Merkwürdig. Bei mir sehe ich sehr deutlich wie sich das Bild öfter von unten nach oben "durchwellt"Fluid Byte hat geschrieben: Macht bei mir keinen Unterschied. Es ruckelt ab und an aber kein Tearing.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
