ClearScreen() für einen Bildschirmbereich

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

ClearScreen() für einen Bildschirmbereich

Beitrag von Lebostein »

Hi,

hat jemand (der sich mit DirectX auskennt) eine schnelle ClearScreen-Routine für einen Bildschirmausschnitt (x1,y1,x2,y2) auf Lager? Eine Box mit den 2DDrawing()-Befehlen zu zeichnen ist für die Performance leider tödlich. Und der Umweg über ein Sprite (Sprite erstellen und einfärben) ist mir zu langsam, vor allem der Befehl CreateSprite() braucht viel Zeit. Irgendwie muss dass doch einfacher gehen, praktisch genau wie der Befehl ClearScreen(), nur dass man den Bereich eingrenzen kann.

(@Stefan Möbius, du hast doch immer so schöne kleine DX-Routinen herumliegen :D)
Stefan
Beiträge: 125
Registriert: 29.08.2004 10:51
Kontaktdaten:

Beitrag von Stefan »

Hi Lebostein
(@Stefan Möbius, du hast doch immer so schöne kleine DX-Routinen herumliegen )
:allright:
Du könntest den ColorBox-Befehl aus meiner SpriteEx-Userlib verwenden:

Code: Alles auswählen

InitSprite()
InitKeyboard()
OpenScreen(800,600,16,"Fast colorboxes")

StartDrawing(ScreenOutput())
PixelFormat=DrawingBufferPixelFormat()
StopDrawing()


Repeat  
  ClearScreen(0,0,0)

  For c=0 To 300
   ColorBox(100,100,50,50,RGBColor(PixelFormat,255,0,0))
  Next
  
  
  Count+1
  If ElapsedMilliseconds()-Start=>1000:Start=ElapsedMilliseconds():FPS=Count:Count=0:EndIf
  
  StartDrawing(ScreenOutput())
  DrawText(Str(FPS))
  StopDrawing()
  
  FlipBuffers(0)
  
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_All)
oder diese Prozedur, wenn du keine Userlibs verwenden willst:(Funktioniert nicht im 8-Bit Farbmodus)

Code: Alles auswählen

Structure DDBLTFX
  dwSize.l
  dwDDFX.l
  dwROP.l
  dwDDROP.l
  dwRotationAngle.l
  dwZBufferOpCode.l
  dwZBufferLow.l
  dwZBufferHigh.l
  dwZBufferBaseDest.l
  dwZDestConstBitDepth.l
  dwZDestConst.l
  dwZSrcConstBitDepth.l
  dwZSrcConst.l
  dwAlphaEdgeBlendBitDepth.l
  dwAlphaEdgeBlend.l
  dwReserved.l
  dwAlphaDestConstBitDepth.l
  dwAlphaDestConst.l
  dwAlphaSrcConstBitDepth.l
  dwAlphaSrcConst.l
  dwFillColor.l
  dwColorSpaceLowValue.l
  dwColorSpaceHighValue.l
  dwColorSpaceLowValue2.l
  dwColorSpaceHighValue2.l
EndStructure
#DDBLT_COLORFILL=1024
#DDBLT_WAIT=16777216

Procedure _GetScreenWidth()
  !extrn _PB_DirectX_ScreenWidth
  !MOV Eax,[_PB_DirectX_ScreenWidth]
  ProcedureReturn
EndProcedure
Procedure _GetScreenHeight()
  !extrn _PB_DirectX_ScreenHeight
  !MOV Eax,[_PB_DirectX_ScreenHeight]
  ProcedureReturn
EndProcedure
Procedure _GetPixelFormat()
  !extrn _PB_DirectX_PixelFormat
  !MOV Eax,[_PB_DirectX_PixelFormat]
  ProcedureReturn 
EndProcedure
Procedure _GetBackBufferSurface()
  !extrn _PB_Sprite_CurrentBitmap
  !MOV Eax,[_PB_Sprite_CurrentBitmap]
  ProcedureReturn
EndProcedure
Procedure _RGBColor(R,G,B)
  Select _GetPixelFormat()
    Case #PB_PixelFormat_15Bits
      ProcedureReturn B>>3+(G>>3)<<5+(R>>3)<<10
    Case #PB_PixelFormat_16Bits    
      ProcedureReturn B>>3+(G>>2)<<5+(R>>3)<<11    
    Case #PB_PixelFormat_24Bits_RGB 
      ProcedureReturn R+G<<8+B<<16 
    Case #PB_PixelFormat_24Bits_BGR    
      ProcedureReturn b+G<<8+R<<16 
    Case #PB_PixelFormat_32Bits_RGB   
      ProcedureReturn R+G<<8+B<<16 
    Case #PB_PixelFormat_32Bits_BGR 
      ProcedureReturn B+G<<8+R<<16   
  EndSelect
EndProcedure




Procedure DrawColorBox(x,y,width,height,RGB) 
  *Back.IDirectDrawSurface7=_GetBackBufferSurface()
  
  a.rect\left=x
  a\right=x+width
  a\top=y
  a\bottom=y+height
  
  b.rect\left=0
  b\right=_GetScreenWidth()
  b\top=0
  b\bottom=_GetScreenHeight()
  
  If IntersectRect_(dest.rect,a.rect,b.rect)=0:ProcedureReturn 0:EndIf
  
  BltInfo.DDBLTFX\dwSize=SizeOf(DDBLTFX)
  BltInfo\dwFillColor=_RGBColor(Red(RGB),Green(RGB),Blue(RGB))
  
  ProcedureReturn *Back\Blt(dest,0,0,#DDBLT_COLORFILL|#DDBLT_WAIT,BltInfo)
EndProcedure







InitSprite()
InitKeyboard()
OpenScreen(800,600,16,"Fast colorboxes")

Repeat
  ClearScreen(0,0,0)  

  For c=0 To 300
    DrawColorBox(100,100,50,50,#red)
  Next


  Count+1
  If ElapsedMilliseconds()-Start=>1000:Start=ElapsedMilliseconds():FPS=Count:Count=0:EndIf
  
  StartDrawing(ScreenOutput())
  DrawText(Str(FPS))
  StopDrawing()
  
  FlipBuffers(0)
  
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_All)
Gruß
Stefan
Zuletzt geändert von Stefan am 07.04.2005 18:27, insgesamt 1-mal geändert.
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Beitrag von Lebostein »

Der Befehl ist ja enorm schnell!! :D
Wow! Genau das hab ich gesucht. Danke!!!

Noch ein paar Fragen:
Ist die Struktur DDBLTFX eine von DirectX vorgegebene Struktur oder stecken da auch Sachen von dir drin? Was genau wird denn mit der Rechteckroutine geprüft bzw. welchen Zweck erfüllt sie in deiner Routine?

-------------------------------

PS: Irgendwie scheint bei der Umrechnung der Farben für den 16-Bit Modus ein Fehler drin zu stecken. Der rote Farbanteil wird richtig umgerechnet aber die Farbe gelb wird z.B. grün dargestellt und weiß wird zu türkis...

Code: Alles auswählen

R = 255
G = 255
B = 255
Debug B>>3+(G>>2)<<6+(R>>3)<<11   ; = 67551
Hier kommt eine Zahl größer als 2^16-1 (65535) heraus, was nicht sein darf. Der Grünanteil wird um1 zuviel nach links geschoben. So müsste es glaube ich richtig sein:

Code: Alles auswählen

    Case #PB_PixelFormat_16Bits
    ; ProcedureReturn B>>3+(G>>2)<<6+(R>>3)<<11     
      ProcedureReturn B>>3+(G>>2)<<5+(R>>3)<<11    
Stefan
Beiträge: 125
Registriert: 29.08.2004 10:51
Kontaktdaten:

Beitrag von Stefan »

Hallo Lebostein
Ist die Struktur DDBLTFX eine von DirectX vorgegebene Struktur oder stecken da auch Sachen von dir drin?
Die Struktur ist von DirectDraw, ich hab sie allerdings etwas vereinfacht.
So sieht die Struktur im Original aus:

Code: Alles auswählen

typedef struct _DDBLTFX{ 
    DWORD dwSize; 
    DWORD dwDDFX; 
    DWORD dwROP; 
    DWORD dwDDROP; 
    DWORD dwRotationAngle; 
    DWORD dwZBufferOpCode; 
    DWORD dwZBufferLow; 
    DWORD dwZBufferHigh; 
    DWORD dwZBufferBaseDest; 
    DWORD dwZDestConstBitDepth; 
    union 
    { 
        DWORD               dwZDestConst; 
        LPDIRECTDRAWSURFACE lpDDSZBufferDest; 
    } DUMMYUNIONNAMEN(1);
    DWORD dwZSrcConstBitDepth; 
    union 
    { 
        DWORD               dwZSrcConst; 
        LPDIRECTDRAWSURFACE lpDDSZBufferSrc; 
    } DUMMYUNIONNAMEN(2);
    DWORD dwAlphaEdgeBlendBitDepth; 
    DWORD dwAlphaEdgeBlend; 
    DWORD dwReserved; 
    DWORD dwAlphaDestConstBitDepth; 
    union 
    { 
        DWORD               dwAlphaDestConst; 
        LPDIRECTDRAWSURFACE lpDDSAlphaDest; 
    } DUMMYUNIONNAMEN(3);
    DWORD dwAlphaSrcConstBitDepth; 
    union 
    { 
        DWORD               dwAlphaSrcConst; 
        LPDIRECTDRAWSURFACE lpDDSAlphaSrc; 
    } DUMMYUNIONNAMEN(4);
    union 
    { 
        DWORD               dwFillColor; 
        DWORD               dwFillDepth; 
        DWORD               dwFillPixel; 
        LPDIRECTDRAWSURFACE lpDDSPattern; 
    } DUMMYUNIONNAMEN(5);
    DDCOLORKEY ddckDestColorkey; 
    DDCOLORKEY ddckSrcColorkey; 
} DDBLTFX,FAR* LPDDBLTFX; 
Was genau wird denn mit der Rechteckroutine geprüft bzw. welchen Zweck erfüllt sie in deiner Routine?
Die Funktion berechnet den Bereich in dem beide Rechtecken(a und b) vorkommen und überprüft zusätzlich ob sie sich überhaupt schneiden.
Das wird benötigt um zu verhindern, dass außerhalb des gültigen Bereichs gezeichnet wird.
PS: Irgendwie scheint bei der Umrechnung der Farben für den 16-Bit Modus ein Fehler drin zu stecken. Der rote Farbanteil wird richtig umgerechnet aber die Farbe gelb wird z.B. grün dargestellt und weiß wird zu türkis...
Stimmt... :roll:
Sorry, Ich hätte den Code etwas besser testen sollen! :oops:
Hab den Code oben korrigiert.
Danke für die Berichtigung. :)

Gruß
Stefan
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Beitrag von Lebostein »

Hab mal das hin- und hergeschiebe der Farbbits vereinfacht und sogar ein wenig beschleunigt. Hier mal der Vergleich der bisherigen Methode und meinem Einfall gestern Nacht im Bett. Die Werte für R, G und B in RGBColorFormat2() entsprechen nicht den Farbwerten, sondern den Farbwerten an der entsprechenden Position. (Debugger ausschalten, sonst keine realen Geschwindigkeiten!):

Code: Alles auswählen

;-----------------------------------------------------------------

Procedure DX_PixelFormat()

  ProcedureReturn #PB_PixelFormat_24Bits_BGR

EndProcedure

;-----------------------------------------------------------------

Procedure RGBColorFormat1(RGB) ;bisheriges Vorgehen

  R = Red(RGB)
  G = Green(RGB)
  B = Blue(RGB)

  Select DX_PixelFormat()

  Case #PB_PixelFormat_15Bits     : ProcedureReturn B >> 3 + (G >> 3) << 5 + (R >> 3) << 10
  Case #PB_PixelFormat_16Bits     : ProcedureReturn B >> 3 + (G >> 2) << 5 + (R >> 3) << 11
  Case #PB_PixelFormat_24Bits_RGB : ProcedureReturn R + G << 8 + B << 16
  Case #PB_PixelFormat_24Bits_BGR : ProcedureReturn B + G << 8 + R << 16
  Case #PB_PixelFormat_32Bits_RGB : ProcedureReturn R + G << 8 + B << 16
  Case #PB_PixelFormat_32Bits_BGR : ProcedureReturn B + G << 8 + R << 16

  EndSelect

EndProcedure

;-----------------------------------------------------------------

Procedure RGBColorFormat2(RGB) ;Andere Möglichkeit

  Select DX_PixelFormat()

  Case #PB_PixelFormat_15Bits
  R = (RGB & $0000F8) << 07
  G = (RGB & $00F800) >> 06
  B = (RGB & $F80000) >> 19

  Case #PB_PixelFormat_16Bits
  R = (RGB & $0000F8) << 08
  G = (RGB & $00FC00) >> 05
  B = (RGB & $F80000) >> 19

  Case #PB_PixelFormat_24Bits_RGB
  R = (RGB & $0000FF)
  G = (RGB & $00FF00)
  B = (RGB & $FF0000)

  Case #PB_PixelFormat_24Bits_BGR
  R = (RGB & $0000FF) << 16
  G = (RGB & $00FF00)
  B = (RGB & $FF0000) >> 16

  Case #PB_PixelFormat_32Bits_RGB
  R = (RGB & $0000FF)
  G = (RGB & $00FF00)
  B = (RGB & $FF0000)

  Case #PB_PixelFormat_32Bits_BGR
  R = (RGB & $0000FF) << 16
  G = (RGB & $00FF00)
  B = (RGB & $FF0000) >> 16

  EndSelect

  ProcedureReturn R + G + B

EndProcedure

;-----------------------------------------------------------------

#count = 10000000
RGB = $FAFAFA

timeGetDevCaps_(TimerCaps.TIMECAPS, SizeOf(TIMECAPS))
timeBeginPeriod_(TimerCaps.TIMECAPS\wPeriodMin)

start = timeGetTime_()
For i = 1 To #count: RGBColorFormat1(RGB): Next i
ende1 = timeGetTime_() - start

start = timeGetTime_()
For i = 1 To #count: RGBColorFormat2(RGB): Next i
ende2 = timeGetTime_() - start

timeEndPeriod_(TimerCaps.TIMECAPS\wPeriodMin)

MessageRequester("Ergebnis:", "Variante1: " + Str(ende1) + "ms" + #CR$ + "Variante2: " + Str(ende2) + "ms")
Antworten