Triple Buffering in Purebasic

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Stefan
Beiträge: 125
Registriert: 29.08.2004 10:51
Kontaktdaten:

Triple Buffering in Purebasic

Beitrag von Stefan »

Hallo
Hier eine kleine Funktion,die es ermöglicht triple buffering in Purebasic zu verwenden: :wink:

Code: Alles auswählen

;######################################## 
;# Use Triple Buffering in PureBasic    # 
;######################################## 

Structure DDPIXELFORMAT 
  dwSize.l 
  dwFlags.l 
  dwFourCC.l 
  dwRGBBitCount.l 
  dwRBitMask.l 
  dwGBitMask.l 
  dwBBitMask.l 
  dwRGBAlphaBitMask.l 
EndStructure 

Structure DDCOLORKEY 
  dwColorSpaceLowValue.l 
  dwColorSpaceHighValue.l 
EndStructure 

Structure DDSCAPS2 
  dwCaps.l 
  dwCaps2.l 
  dwCaps3.l 
  dwCaps4.l 
EndStructure 

Structure DDSURFACEDESC2 
  dwSize.l 
  dwFlags.l 
  dwHeight.l 
  dwWidth.l 
  lPitch.l 
  dwBackBufferCount.l 
  dwRefreshRate.l 
  dwAlphaBitDepth.l 
  dwReserved.l 
  lpSurface.l 
  ddckCKDestOverlay.DDCOLORKEY 
  ddckCKDestBlt.DDCOLORKEY 
  ddckCKSrcOverlay.DDCOLORKEY 
  ddckCKSrcBlt.DDCOLORKEY 
  ddpfPixelFormat.DDPIXELFORMAT 
  ddsCaps.DDSCAPS2 
  dwTextureStage.l 
EndStructure 

#DDSD_CAPS=1 
#DDSD_BACKBUFFERCOUNT=32 
#DDSCAPS_BACKBUFFER=4 
#DDSCAPS_3DDEVICE=8192 
#DDSCAPS_PRIMARYSURFACE=512 
#DDSCAPS_FLIP=16 
#DDSCAPS_COMPLEX=8 



Procedure OpenScreenEx(Width,Height,bpp,NbOfBuffers,Title$) ;doesn't work with the OGRE-Engine. 
  !extrn _PB_Engine3D_Initialized 
  !extrn _PB_DirectX_PrimaryBuffer 
  !extrn _PB_DirectX_BackBuffer 
  !extrn _PB_DDrawBase 
  
  If NbOfBuffers<2:ProcedureReturn 0:EndIf ; We need at least double buffering. 
  
  OGREUsed.l 
  *FrontDDS.IDirectDrawSurface7 
  *BackDDS.IDirectDrawSurface7 
  *DD.IDirectDraw7 
  
  !MOV Eax,[_PB_Engine3D_Initialized] 
  !MOV [esp+20],Eax 
  
  If OGREUsed:ProcedureReturn 0:EndIf     ;We can't change the number of Buffers if we use the OGRE-Engine. 
  OpenScreenResult=OpenScreen(Width,Height,bpp,Title$) 
  If OpenScreenResult=0:ProcedureReturn 0:EndIf 
  
  !MOV Eax,[_PB_DirectX_PrimaryBuffer] 
  !MOV [esp+24],Eax 
  !MOV Eax,[_PB_DirectX_BackBuffer] 
  !MOV [esp+28],Eax 
  !MOV Eax,[_PB_DDrawBase] 
  !MOV [esp+32],Eax 
  
  If NbOfBuffers>2 ; change the number of Buffers. 
    
    DDSDESC.DDSURFACEDESC2 
    DDSDESC\dwSize=SizeOf(DDSURFACEDESC2) 
    
    If *FrontDDS\GetSurfaceDesc(DDSDESC) 
      CloseScreen():ProcedureReturn 0 
    EndIf 
    
    DEVICE3D=DDSDESC\ddsCaps\dwCaps&#DDSCAPS_3DDEVICE 
    
    RtlZeroMemory_(DDSDESC,SizeOf(DDSURFACEDESC2)) 
    
    DDSDESC\dwSize=SizeOf(DDSURFACEDESC2) 
    DDSDESC\dwFlags=#DDSD_CAPS|#DDSD_BACKBUFFERCOUNT 
    DDSDESC\ddsCaps\dwCaps=#DDSCAPS_PRIMARYSURFACE|#DDSCAPS_FLIP|#DDSCAPS_COMPLEX|DEVICE3D 
    DDSDESC\dwBackBufferCount=NbOfBuffers-1 
    
    ;*BackDDS\Release() is automatically released 
    *FrontDDS\Release() 
    
    *BackDDS=0 
    *FrontDDS=0 
    
    !MOV dword[_PB_DirectX_PrimaryBuffer],0 
    !MOV dword[_PB_DirectX_BackBuffer],0 
    
    Result=*DD\CreateSurface(DDSDESC,@*FrontDDS,0) 
    If Result:ProcedureReturn 0:EndIf 
    
    ddsCaps.DDSCAPS2 
    ddsCaps\dwCaps=#DDSCAPS_BACKBUFFER    
    Result=*FrontDDS\GetAttachedSurface(ddsCaps,@*BackDDS) 
    If Result:*FrontDDS\Release():ProcedureReturn 0:EndIf 
    
    !MOV Eax,[esp+24] 
    !MOV dword[_PB_DirectX_PrimaryBuffer],Eax 
    !MOV Eax,[esp+28] 
    !MOV dword[_PB_DirectX_BackBuffer],Eax 
  EndIf 
  
  ProcedureReturn OpenScreenResult 
EndProcedure 






;Example: 


InitSprite() 
InitSprite3D() 
InitKeyboard() 
Result=OpenScreenEx(800,600,16,3,"Triple Buffering Test") 

If Result=0 
  MessageRequester("ERROR","Can't open screen !") 
  End 
EndIf 


CreateSprite(1,64,64,#PB_Sprite_Texture) 
StartDrawing(SpriteOutput(1)) 
Box(0,0,64,64,#yellow) 
DrawingFont(LoadFont(1,"Arial Black",10)) 
DrawingMode(1) 
FrontColor(0,0,128) 
DrawText("Enjoy") 
Locate(0,18) 
DrawText("Triple-") 
Locate(0,36) 
DrawText("buffering") 
StopDrawing() 
CreateSprite3D(1,1) 


RandomSeed(3) 


For count=0 To 2   ; fill all 3 buffers 
  ClearScreen(0,0,0) 
  Start3D() 
  Sprite3DQuality(1) 
  ZoomSprite3D(1,256,256) 
  RotateSprite3D(1,30,0) 
  DisplaySprite3D(1,Random(800-256),Random(600-256)) 
  Stop3D() 
  FlipBuffers() 
  Delay(500) 
Next 

Repeat 
  FlipBuffers() 
  Delay(500) 
  ExamineKeyboard() 
Until KeyboardPushed(#PB_Key_Escape) 
Gruß
Stefan
Benutzeravatar
Spirit
Beiträge: 174
Registriert: 13.04.2005 19:09

Beitrag von Spirit »

Ich habe dazu mal eine Frage:
Welche praktische Bedeutung hat Triple Buffering eigentlich? Wo ist da der Vorteil gegenüber Double Buffering?
Benutzeravatar
diGGa
Beiträge: 249
Registriert: 01.04.2005 11:00
Kontaktdaten:

Beitrag von diGGa »

vielleicht weichere übergänge... noch weniger ruckler..
Stefan
Beiträge: 125
Registriert: 29.08.2004 10:51
Kontaktdaten:

Beitrag von Stefan »

Hallo BlueSpirit
Du hast doch bestimmt schon mal bemerkt, dass du mehr Bilder pro Sekunde
bekommst wenn du die vertikale Synchronisation ausschaltest obwohl die
Anzahl der Bilder pro Sekunde eigentlich unter der Refreshrate des Monitors liegt.
(Wenn nicht solltest du es mal ausprobieren :wink: )
Das liegt daran, dass bei double buffering solange gewartet werden muss
bis der Monitor mit dem Bildaufbau des vorherigen Bildes fertig ist.
Bei triple buffering muss nicht gewartet werden.
Im idealsten Fall kann man mit triple buffering die Anzahl der Bilder pro Sekunde verdoppeln.
@diGGa
Die Übergänge werden durch Triple Buffering nicht weicher.

Hier noch ein Link zu diesem Thema:
http://www.3dcenter.de/artikel/2004/03-12_a.php

Gruß
Stefan
Benutzeravatar
nco2k
Beiträge: 892
Registriert: 08.09.2004 23:13

Beitrag von nco2k »

~|__/
..o.o.. <--- This is Einkaufswagen. Copy Einkaufswagen into your signature to help him on his way to world domination.
Antworten