Seite 1 von 1

Offscreen Rendering in einem Sprite/Fake Viewport

Verfasst: 08.09.2025 13:18
von boulderdash
Hallo,
ich möchte ein leeres Sprite in der Größe z. B. von 320 x 256 Pixel erzeugen und in diesem Sprite meine Grafiken wie andere Sprites oder Tiles zeichnen.
Wenn alles gezeichnet ist, soll das große Sprite auf dem Screen skaliert und zentriert gezeichnet werden.
Ist das überhaupt möglich?
Oder gibt es eine Art Viewport den ich einstellen kann, damit nur in diesem Bereich gezeichnet wird (ClipOutput funktioniert ja nicht mit 2D Sprites)

Nachtrag:
Ich öffne einen Screen mit der nativen Desktop-Auflösung also z. B. 1920 x 1080 Pixel. Wie ich festgestellt habe, erfolgt keine Umschaltung in einem exklusiven Grafik-Modus, geht sehr schnell und mit ALT+TAB das wechseln zum Desktoptop auch, das ist schonmal sehr gut.

Wenn meine selbst ausgewählte Auflösung 320 x 256 Pixel hat, dann soll dieser Ausschnitt skaliert und zentriert werden, somit würde der Bildschirm nicht komplett ausgefüllt sein, sondern erst bei Position X=320, Y=28 beginnen und die Gesamtgröße der Grafik 1280 x 256 Pixel betragen (4 fach skaliert),

Code: Alles auswählen

scale = DesktopHeight / 256 = 4
X-Position = (DesktopWidth - (320 * scale)) / 2
Y-Position = (DesktopHeight - (256* scale)) / 2

sizeX = 320 * 4 = 1280
sizeY = 256 * 4 = 1024
Über eine Antwort freue ich mich

Vielen Dank.

Re: Offscreen Rendering in einem Sprite /Fake Viewport

Verfasst: 08.09.2025 18:03
von boulderdash
In der Purebasic Dokumentation habe ich leider nichts weiter gefunden. Als Notlösung habe ich ein Sprite als Overlay mit schwarzen Rändern wie ich es brauche erstellt und lege es einfach über alle anderen Sprites <)

Re: Offscreen Rendering in einem Sprite

Verfasst: 08.09.2025 18:39
von #NULL
boulderdash hat geschrieben: 08.09.2025 13:18 und in diesem Sprite meine Grafiken wie andere Sprites oder Tiles zeichnen.
Wenn du die Grafiken/Tiles als Images vorliegen hast, kannst du sie mit StartDrawing/SpriteOutput auf das Sprite zeichnen (mit DrawingMode AllChannels). Wenn es bereits Sprites sind, kannst du sie auf den Screen 'displayn' und danach mit GrabSprite wieder ein Sprite daraus erzeugen. Ich weiß aber gerade nicht ob du dabei deine [Alpha]kanäle erhalten kannst.

Re: Offscreen Rendering in einem Sprite /Fake Viewport

Verfasst: 08.09.2025 18:49
von boulderdash
#NULL hat geschrieben: 08.09.2025 18:39
boulderdash hat geschrieben: 08.09.2025 13:18 und in diesem Sprite meine Grafiken wie andere Sprites oder Tiles zeichnen.
Wenn du die Grafiken/Tiles als Images vorliegen hast, kannst du sie mit StartDrawing/SpriteOutput auf das Sprite zeichnen (mit DrawingMode AllChannels). Wenn es bereits Sprites sind, kannst du sie auf den Screen 'displayn' und danach mit GrabSprite wieder ein Sprite daraus erzeugen. Ich weiß aber gerade nicht ob du dabei deine [Alpha]kanäle erhalten kannst.
Danke für Deine Antwort. Aber ich glaube mit GrabImage wird das nicht gerade performant.

Re: Offscreen Rendering in einem Sprite /Fake Viewport

Verfasst: 08.09.2025 19:04
von boulderdash
Ich habe das mit dem Sprite-Overlay mal in ein Module verpackt.

Code: Alles auswählen

; Sprite Overlay für 4:3 retro look auf einem 16:x Display erzeugen
; Init() - Erzeugt das entsprechende Sprite Overlay
; Draw() - Zeichnet das Sprite Overlay (muß als letztes Sprite im Loop gezeichnet werden)
; Free() - Speicherfreigabe

DeclareModule DisplaySpriteOverlay
  ; gameWidth, gameHeight = native Spielauflösung in Pixeln
  Declare.i Init(gameWidth.i, gameHeight.i)
  Declare.i Draw()
  Declare.i Free()
EndDeclareModule

Module DisplaySpriteOverlay
  EnableExplicit
  
  Global spriteId.i  
  Global xOffset.i, yOffset.i
  Global overlayWidth.i, overlayHeight.i
  
  ; gameWidth, gameHeight = native Spielauflösung in Pixeln
  Procedure.i Init(gameWidth.i, gameHeight.i)   
    ; Desktop-Auflösung ermitteln, Skalierungsfaktor und Overlay-Abmessungen berechnen 
    ExamineDesktops()
    Define deskW.i = DesktopWidth(0)
    Define deskH.i = DesktopHeight(0)
    
    Define scale.i = deskH / gameHeight
    If scale < 1
      scale = 1
    EndIf
    
    xOffset = (deskW - gameWidth) / 2
    yOffset = (deskH - gameHeight) / 2
    
    overlayWidth = deskW / scale
    overlayHeight = deskH / scale

    spriteId = CreateSprite(#PB_Any, overlayWidth, overlayHeight, #PB_Sprite_AlphaBlending)
    If Not spriteId
      ProcedureReturn #False
    EndIf
    
    ; Sprite-Overlay erzeugen mit einem schwarzen Bereich an allen Seiten (Windowboxing)
    StartDrawing(SpriteOutput(spriteId))
      Box(0, 0, overlayWidth, overlayHeight, RGB(0, 0, 0))
      
      DrawingMode(#PB_2DDrawing_AlphaChannel)
      Box((overlayWidth - gameWidth) / 2, (overlayHeight - gameHeight) / 2, gameWidth, gameHeight, $00000000)
      DrawingMode(#PB_2DDrawing_Default)    
    StopDrawing()
    
    ; Overlay für die Zielauflösung skalieren
    ZoomSprite(spriteId, overlayWidth * scale, overlayHeight * scale)
    
    ProcedureReturn #True
  EndProcedure
  
  Procedure Draw()
    DisplayTransparentSprite(spriteId, 0, 0)
  EndProcedure
  
  Procedure Free()
    If IsSprite(spriteId)
      FreeSprite(SpriteID)
    EndIf   
  EndProcedure
EndModule