Aktuelle Zeit: 31.10.2020 13:13

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: DisplayTransparentSprite & AlphaKanal-Problem
BeitragVerfasst: 22.04.2020 22:54 
Offline

Registriert: 31.08.2004 00:11
Wohnort: Mannheim
Hi Leute!

ich steh sehr gewaltig auf dem Schlauch.
Ich erstelle ein Image mit Transparenz-Flag, erstelle ein Sprite mit AlphaBlending-Flag.
Auf das Image zeichne ich mit Vector-Funktionen ein wenig zum testen, zeichne das Image mit DrawAlphaImage auf das Sprite und lasse es mit DisplayTransparentSprite überlappend anzeigen.

Leider klappt es mit der Transparenz nicht, wie ich mir das vorstelle.
Lasse ich das Flag #PB_Sprite_AlphaBlending bei der Sprite-Erstellung weg, hat es nur einen Pseudo-Effekt. In diesem Moment wird nur Schwarz als Transparent angesehen, was aber nicht zweck der Übung ist.
Kann mir irgendwer auf die Sprünge helfen, wie ich die 2 Sprites unter Berücksichtigung des Alphakanals korrekt übereinander gelegt bekomme, sodass beide gerundeten Rechtecke korrekt und mit sauberer Kontur zu sehen sind und die 2 roten Flächen an der Stelle der Überlappung kräftiger werden (also wie normal zu erwarten)?

Für mein eigentliches Programm bin ich auf die Vector-Befehle angewiesen um zur Laufzeit Grafiken für die Sprites zu erstellen - allerdings ohne funktionierendes Alpha stehe ich jetzt vor einer Wand :-(
Danke euch schon mal riesig für einen kleinen Denkanstoß und hoffentlich einen guten Schlag gegen den Kopf.

Hier der Beispielcode zum aufzeigen meines Problems und wie ich es aktuell dachte zu lösen.
Zu erkennen, dass ich auch schon etwas mit DrawingMode und weglassen des Flags bei CreateSprite getestet habe, leider ohne Erfolg.

PS: Nicht wundern in der Procedure über sizeX und sizeY - bin kein Freund der Bezeichnungen width und heigth

Code:
Procedure AddPathBoxRounded(x, y, sizeX, sizeY, radius, flags = #PB_Path_Default)
   MovePathCursor(x + radius, y, flags)
   AddPathArc(sizeX-radius, 0, sizeX-radius, radius, radius, #PB_Path_Relative)
   AddPathArc(0, sizeY-radius, -radius, sizeY-radius, radius, #PB_Path_Relative)
   AddPathArc(-sizeX+radius, 0, -sizeX+radius, -radius, radius, #PB_Path_Relative)
   AddPathArc(0, -sizeY+radius, radius, -sizeY+radius, radius, #PB_Path_Relative)
EndProcedure

If InitSprite() = 0
   MessageRequester("Error", "Can't open screen & sprite environment!", 0)
   End
EndIf

OpenWindow(0, 0, 0, 400, 300, "Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0), 0, 0, 400, 300, 0, 0, 0, #PB_Screen_WaitSynchronization)

tempimg = CreateImage(#PB_Any, 100, 100, 32, #PB_Image_Transparent)
spr = CreateSprite(#PB_Any, 100, 100, #PB_Sprite_AlphaBlending)
;spr = CreateSprite(#PB_Any, 100, 100)

If StartVectorDrawing(ImageVectorOutput(tempimg, #PB_Unit_Pixel))
   AddPathBoxRounded(1, 1, 98, 98, 40)
   VectorSourceColor(RGBA(255, 255, 255, 255))
   StrokePath(1, #PB_Path_Default)
   AddPathBox(40, 40, 20, 20)
   VectorSourceColor(RGBA(255, 0, 0, 100))
   FillPath()
   StopVectorDrawing()
EndIf

StartDrawing(SpriteOutput(spr))
   ;DrawingMode(#PB_2DDrawing_AlphaBlend)
   DrawAlphaImage(ImageID(tempimg), 0, 0)
StopDrawing()


Repeat
   Repeat
      event = WindowEvent()
      Select event
         Case #PB_Event_CloseWindow : End
      EndSelect
   Until event = 0
   
   FlipBuffers()
   ClearScreen(RGB(127, 127, 127))
   DisplayTransparentSprite(spr, 0, 0)
   DisplayTransparentSprite(spr, 10, 10)
   Delay(2)
ForEver


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: DisplayTransparentSprite & AlphaKanal-Problem
BeitragVerfasst: 22.04.2020 23:08 
Offline
Kommando SG1
Benutzeravatar

Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Hallo KTX82,

StartDrawing() unterstützt bei SpriteOutput() leider nicht (offiziell) den Alpha-Kanal.
Ich sage deswegen offiziell, weil du theoretisch mit DrawingBuffer() das Sprite auch im Alpha-Kanal ändern könntest.

Die Einfachste Methode ist jedoch, einfach das Image mit EncodeImage speichern und dann mit CatchSprite wieder einlesen:
Code:
Procedure CreateSpriteFromImage(Sprite.i, Image.i)
   Protected *Buffer, Result.i
   *Buffer = EncodeImage(Image, #PB_ImagePlugin_PNG)
   Result = CatchSprite(Sprite, *Buffer, #PB_Sprite_AlphaBlending)
   FreeMemory(*Buffer)
   ProcedureReturn Result
EndProcedure

Du brauchst dafür aber UsePNGImageDecoder() und UsePNGImageEncoder()

_________________
Bild
 
BildBildBild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: DisplayTransparentSprite & AlphaKanal-Problem
BeitragVerfasst: 23.04.2020 08:44 
Offline
Benutzeravatar

Registriert: 23.07.2011 02:08
STARGÅTE hat geschrieben:
StartDrawing() unterstützt bei SpriteOutput() leider nicht (offiziell) den Alpha-Kanal.
Ich sage deswegen offiziell, weil du theoretisch mit DrawingBuffer() das Sprite auch im Alpha-Kanal ändern könntest.

Die Einfachste Methode ist jedoch, einfach das Image mit EncodeImage speichern und dann mit CatchSprite wieder einlesen:


D'oh /:->

Das hat mich auch schon jede Menge Nerven gekostet. Danke für DEN Hinweis :praise:

_________________
Signatur und so


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: DisplayTransparentSprite & AlphaKanal-Problem
BeitragVerfasst: 23.04.2020 13:05 
Offline

Registriert: 31.08.2004 00:11
Wohnort: Mannheim
Hallo STARGÅTE :)

Danke für die super Antwort. Als ich im Forum zuvor wegen diesem Problem recherchiert habe, habe ich zwar ein wenig gefunden, aber nichts, was zu 100% dieses Verhalten erklärt. Und zusätzlich danke für die einfache Lösung.

Ich werde meine Riecher aber mal nach der Variante mit DrawingBuffer() ausstrecken und ein paar Versuche wagen, da der Umweg über den PNG En-/Decoder zwar in der Tat sehr einfach ist, jedoch denke ich massig Performance schluckt wenn es darum geht sehr viele Sprites (100+) in kaum wahrnehmbarer Zeit zu erstellen.

Da ich mangels Erfahrung und früher nie damit beschäftigt, nicht so firm im Umgang mit Pointern bin, was ja, wie ich überall lese sehr gute Performanceverbesserungen bewirken soll, werde ich nach Erfolg hier hoffentlich trotzdem eine Procedere posten können, mit der man ein Image mit Alpha-Kanal dann in ein Sprite setzt. Sollte es dann natürlich einen einfachen Code in irgendeinem Post schon hierfür geben, wäre ich auch da über einen kleinen Hinweis dankbar, werde aber trotzdem versuchen erst mal selbst diesen Teil gelöst zu bekommen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: DisplayTransparentSprite & AlphaKanal-Problem
BeitragVerfasst: 23.04.2020 15:56 
Offline
Kommando SG1
Benutzeravatar

Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Der Beitrag hier ist zwar etwas älter, sollte aber noch funktionieren (wobei ja heute kein Sprite3D mehr nötig ist):
https://www.purebasic.fr/german/viewtopic.php?p=281008#p281008
(Funktioniert aber nur, wenn Image und Sprite im 32-Bit-Format vorliegen, weil der Fall sein sollte, wenn beides mit AlphaKanal erzeugt wird)

_________________
Bild
 
BildBildBild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: DisplayTransparentSprite & AlphaKanal-Problem
BeitragVerfasst: 25.04.2020 17:20 
Offline

Registriert: 31.08.2004 00:11
Wohnort: Mannheim
Klasse! Der Code funktioniert in der Tat immer noch einwandfrei.
Ich habe mir erlaubt die Procedure nur minimal anzupassen, da zumindest für den Verwendungszweck mit dem Alphakanal eh immer #PB_Sprite_AlphaBlending benötigt wird und nur wahlweise #PB_Sprite_PixelCollision hinzukommt. So wird im Normalfall die Angabe des Flags bei Aufruf der Procedure nicht benötigt.

Mit dieser Procedure muss man zwar den gewünschten Sprite-Inhalt zuvor "vollständig" auf einem Image zeichnen und kann nicht diverse Images an verschiedenen Positionen ins Sprite nach und nach setzen, aber so wie es jetzt ist, ist exakt was ich benötige :-)
Und der Geschwindigkeitsvorteil + wesentlich weniger CPU-Last im Vergleich zur Variante mit dem Umweg über den PNG En-/Decoder ist gewaltig.

Schade, dass es so eine Funktion nicht in hoch optimierter Form schon mit den Bordmitteln gibt - irgendwie fast nicht nachvollziehbar für mich, da es für mich wie eine essentielle Grundlage wirkt.... hmmmm....
Hier jetzt aber noch der lauffähige Code mit der leicht angepassten Procedure:

Code:
Procedure AddPathBoxRounded(x, y, sizeX, sizeY, radius, flags = #PB_Path_Default)
   MovePathCursor(x + radius, y, flags)
   AddPathArc(sizeX - radius, 0, sizeX - radius, radius, radius, #PB_Path_Relative)    ;oben
   AddPathArc(0, sizeY - radius, -radius, sizeY - radius, radius, #PB_Path_Relative)    ;rechts
   AddPathArc(-sizeX + radius, 0, -sizeX + radius, -radius, radius, #PB_Path_Relative)    ;unten
   AddPathArc(0, -sizeY + radius, radius, -sizeY + radius, radius, #PB_Path_Relative)   ;links
EndProcedure

Procedure CreateSpriteFromAlphaImage(sprite, image, flags = #PB_Sprite_AlphaBlending)
   Protected row
   Protected imageHeight = ImageHeight(image)
   Protected imageWidth  = ImageWidth(image)
   Protected *ReadBuffer,  readPitch,  readFormat
   Protected *WriteBuffer, writePitch, writeFormat
   If flags = #PB_Sprite_PixelCollision
      flags | #PB_Sprite_AlphaBlending
   EndIf
   StartDrawing(ImageOutput(image))
      *ReadBuffer = DrawingBuffer()
      readPitch = DrawingBufferPitch()
      readFormat = DrawingBufferPixelFormat()
   StopDrawing()
   If sprite = #PB_Any
      sprite = CreateSprite(#PB_Any, imageWidth, imageHeight, flags)
   Else
      CreateSprite(sprite, imageWidth, imageHeight, flags)
   EndIf
   StartDrawing(SpriteOutput(sprite))
      *WriteBuffer = DrawingBuffer()
      writePitch = DrawingBufferPitch()
      writeFormat = DrawingBufferPixelFormat()
      If readFormat & #PB_PixelFormat_ReversedY XOr writeFormat & #PB_PixelFormat_ReversedY
         For row = 0 To imageHeight - 1
            CopyMemory(*ReadBuffer + (imageHeight - 1 - row) * readPitch, *WriteBuffer + row * writePitch, imageWidth * SizeOf(Long))
         Next
      Else
         For row = 0 To imageHeight - 1
            CopyMemory(*ReadBuffer + row * readPitch, *WriteBuffer + row * writePitch, imageWidth * SizeOf(Long))
         Next
      EndIf
   StopDrawing()
   ProcedureReturn sprite
EndProcedure

If InitSprite() = 0
   MessageRequester("Error", "Can't open screen & sprite environment!", 0)
   End
EndIf

OpenWindow(0, 0, 0, 400, 300, "Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0), 0, 0, 400, 300, 0, 0, 0, #PB_Screen_WaitSynchronization)

tempimg = CreateImage(#PB_Any, 100, 100, 32, #PB_Image_Transparent)
If StartVectorDrawing(ImageVectorOutput(tempimg, #PB_Unit_Pixel))
   AddPathBoxRounded(1, 1, 98, 98, 40)
   VectorSourceColor(RGBA(255, 255, 255, 255))
   StrokePath(2, #PB_Path_Default)
   AddPathBox(40, 40, 20, 20)
   VectorSourceColor(RGBA(255, 0, 0, 100))
   FillPath()
   StopVectorDrawing()
EndIf
spr = CreateSpriteFromAlphaImage(#PB_Any, tempimg)

Repeat
   Repeat
      event = WindowEvent()
      Select event
         Case #PB_Event_CloseWindow : End
      EndSelect
   Until event = 0
   
   FlipBuffers()
   ClearScreen(RGB(0, 0, 0))
   DisplayTransparentSprite(spr, 0, 0)
   DisplayTransparentSprite(spr, 10, 10)
   Delay(2)
ForEver


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye