syncronisieren von/mit Window Redraw

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

syncronisieren von/mit Window Redraw

Beitrag von Thorium »

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?
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Rokur
Beiträge: 167
Registriert: 29.12.2005 09:58
Computerausstattung: Intel Core2 Quad (4x2,4 GHz), 4096 MB RAM, GForce 8800GTX 786 MB
Windows XP 32 Bit, PureBasic 4.40 (x86)

Beitrag von Rokur »

Wie zeichnest du denn aufs Fenster? Mit Doublebuffering sollte da doch eigentlich nichts passieren können.
WinXP 32 Bit, PureBasic 4.40 (x86)
Benutzeravatar
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:

Beitrag von coder »

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!
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

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_CloseWindow
Windows 10 Pro, 64-Bit / Outtakes | Derek
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

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.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

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.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Ich denke ein kleiner Beispielcode würde hier helfen dein Problem etwas besser zu verstehen.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Fluid Byte hat geschrieben:Ich denke ein kleiner Beispielcode würde hier helfen dein Problem etwas besser zu verstehen.
OK

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! Bild
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Also ob nun dein Beispiel mit GDI oder per Screen

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 
Macht bei mir keinen Unterschied. Es ruckelt ab und an aber kein Tearing.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Fluid Byte hat geschrieben: Macht bei mir keinen Unterschied. Es ruckelt ab und an aber kein Tearing.
Merkwürdig. Bei mir sehe ich sehr deutlich wie sich das Bild öfter von unten nach oben "durchwellt"
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Antworten