Sprite mit Alpha - was passiert da?

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
sire
Beiträge: 10
Registriert: 25.11.2005 02:09

Sprite mit Alpha - was passiert da?

Beitrag von sire »

Daß die Alpha-Sprites in PureBasic nicht wirklich das sind, was man sich unter Sprites mit Alpha-Channel normalerweise vorstellen würde, diese Entdeckung habe ich schon eine Weile hinter mir. Nur - wie funktionieren die denn nun wirklich? Es sieht ganz so aus, als handle es sich um so etwas wie additive Transparenz. Der Grauton mit dem Wert 128 ist aber in Wirklichkeit auch keineswegs voll durchsichtig, so wie in der Dokumentation behauptet. Jedenfalls nicht bei mir. Da, wo in den Sprites Pixel diesen Helligkeitswert haben, verdunkeln sie den Hintergrund immer noch leicht. Die Pixel mit Helligkeit 255 fallen wiederum auch nicht ganz weiß aus, es sei denn, man setzt die Alpha-Intensity auf 255,255,255. Dann ist aber auch sonst nichts mehr transparent. Bei Alpha-Intensity 0,0,0 sind die Alpha-Sprites außerdem nicht voll durchsichtig, wie man meinen sollte ...

Wieso wird der Kram eigentlich als "Alpha-Blending" bezeichnet? Diese irreführende Namensgebung ist schlimm genug, doch was stattdessen da denn nun vor sich geht, darüber gibt die Anleitung leider auch keine vernünftige Auskunft. Oder habe ich da irgendwas Entscheidendes übersehen bzw. nicht begriffen?
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

Die Alphaintensity geht von -(512/2) bis +(512/2) (oder mehr)

gugge mal

Code: Alles auswählen

If InitSprite() = 0 Or InitKeyboard() = 0
  MessageRequester("Error", "Can't open DirectX 7 or later", 0)
  End
EndIf
If OpenWindow(0,0,0,320,240,#PB_Window_SystemMenu,"Beenden mit ESC")
  If OpenWindowedScreen(WindowID(0),0,0,WindowWidth(),WindowHeight(),1,0,0)
    LoadSprite(0, "kerze.bmp", 0)
    LoadSprite(1,"alpha.bmp",#PB_Sprite_Alpha)
    ShowCursor_(0)
    dir=10
    Repeat
      FlipBuffers()
      ClearScreen(0,0,0)
      DisplaySprite(0, 0, 0)
      w+dir
      If w>=256
        dir= -10
      EndIf
      If w <=-256
        dir= 10
      EndIf
      ChangeAlphaIntensity(w,w,w)
      DisplayAlphaSprite(1, 0,0)
      ExamineKeyboard()
      While WindowEvent():Wend
    Until KeyboardPushed(#PB_Key_Escape)
  Else
    MessageRequester("Error", "Can't open a 640*480 - 16 bit screen !", 0)
  EndIf
EndIf
End
Kerze.bmp beinhaltet einen Tisch mit Kerze (256 Farben)
und Alpha den Flammenteil leicht angegraut den Rest dunkel (8 Bit Graustufe)
Kannst Du nebst Bilder auch hier runterladen
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
sire
Beiträge: 10
Registriert: 25.11.2005 02:09

Beitrag von sire »

Aha, negative Werte gehen also auch... Aber auf was für einer Formel die Verknüpfung des Alphasprites mit dem Hintergrund beruht, erschließt sich mir immer noch nicht ganz.

Ich hab zum Rumprobieren Deinen Code mal etwas modifiziert:

Code: Alles auswählen

If InitSprite() = 0 Or InitKeyboard() = 0
  MessageRequester("Error", "Can't open DirectX 7 or later", 0)
  End
EndIf
If OpenWindow(0,0,0,320,240,#PB_Window_SystemMenu,"Beenden mit ESC")
  If OpenWindowedScreen(WindowID(0),0,0,WindowWidth(),WindowHeight(),1,0,0)
    LoadSprite(0, "testchart_bg.bmp", 0)
    LoadSprite(1,"testchart_fg.bmp",#PB_Sprite_Alpha)
    Repeat
      FlipBuffers()
      ClearScreen(0,0,0)
      DisplaySprite(0, 0, 0)
      w=WindowMouseY()*1024/240-512
      ChangeAlphaIntensity(w,w,w)
      DisplayAlphaSprite(1, 0,0)
      StartDrawing(ScreenOutput())
      DrawText(Str(w))
      StopDrawing()
      ExamineKeyboard()
      While WindowEvent():Wend
    Until KeyboardPushed(#PB_Key_Escape)
  Else
    MessageRequester("Error", "Can't open a 640*480 - 16 bit screen !", 0)
  EndIf
EndIf
End
Diesen Code mit anderen Bildern, die ich zum Forschen praktischer fand, wiederum hier zum Runterladen.

Bemerkenswert: Nicht der Grauton mit Wert 128 ist immer voll transparent, sondern jener mit dem Helligkeitswert 149! Jedenfalls bei mir. Ist das überall so? Komisch krumm irgendwie, der Wert. Warum ist nicht einfach die Farbe 0 transparent? Auch sonst alles irgendwie krumm: Wenn ich die Alpha-Intensity in obigem Programm soweit hochregle, daß links unten in den beiden Testbildern schwarze Pixel im Alphasprite über schwarzen Pixeln im Hintergrund weiß ergeben, liegt der Intensity-Wert bei etwa 390. Umgekehrt scheint bei etwa -390 Weiß auf Weiß schwarz zu werden (allein multiplikative Verknüpfung scheidet also aus, allein additiv würde andererseits Farben verfälschen, sobald es einen Overflow in einer der Komponenten gibt; es scheint so eine Art Überblendung in Weiß bzw. Schwarz zu sein).

Als denkbarer Grund für die Krummheit der Werts der durchsichtigen Farbe fällt mir gerade noch ein, daß PB vielleicht einfach nach dem 128. Eintrag in der 256-Farb-Palette eines BMPs guckt, und dessen Inhalt muß ja nicht unbedingt ebenfalls 128 betragen. Wenn dem so wäre, wäre die transparente Farbe kaum vorhersehbar, man müßte bei der Erstellung der Alphagrafik darauf achten, daß die passende Farbe in jener Palettenzelle landet.
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

Bei mir ist immer der 128er volltransparent .. der 128er-Streifen ändert
sich nicht und es bleibt auch immer ein Ring sichtbar.
Ein Umkippen von weiß nach schwarz oder andersrum kann ich nith nachvollziehen. Es wird halt schwarz (Maus hoch) oder Weiß (Maus runter)

Als Alphasprite gehen lt. Dokumentation immer nur GraustufenBilder ..und da ist die 128te Stelle ein 128er Graustufenwert, oder?
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
sire
Beiträge: 10
Registriert: 25.11.2005 02:09

Beitrag von sire »

bobobo hat geschrieben:Bei mir ist immer der 128er volltransparent .. der 128er-Streifen ändert
sich nicht und es bleibt auch immer ein Ring sichtbar.
Hm, sonderbar. Bei mir ist das anders. Ist ein Laptop mit nem Radeon x600.
Ein Umkippen von weiß nach schwarz oder andersrum kann ich nith nachvollziehen. Es wird halt schwarz (Maus hoch) oder Weiß (Maus runter)
Ja, klar. Aber es wird eben selbst dort ganz weiß, wo sowohl im Hintergrund als auch im Vordergrund (also im Alpha-Sprite) eigentlich nur schwarze Pixel sind. Das lieferte mir Anhaltspunkte zur wahrscheinlichen Verknüpfungsformel, die demzufolge nicht einfach nur additives Blending beinhalten kann. Die Verknüpfung scheint mir etwa so auszusehen:

Code: Alles auswählen

AlphaPixel/2+64  ; Amplitude wird halbiert
AlphaPixelR=AlphaPixel+IntensityR  ; Intensity-Werte können auch negativ sein, wie erwähnt
AlphaPixelG=AlphaPixel+IntensityG
AlphaPixelB=AlphaPixel+IntensityB

If AlphaPixel>128
  ResultPixelR=AlphaPixelR+(255-AlphaPixelR)*BGPixelR/255
  ResultPixelG=AlphaPixelG+(255-AlphaPixelG)*BGPixelG/255
  ResultPixelB=AlphaPixelB+(255-AlphaPixelB)*BGPixelB/255
ElseIf AlphaPixel<128
  ResultPixelR=AlphaPixelR/255*BGPixelR
  ResultPixelG=AlphaPixelG/255*BGPixelG
  ResultPixelB=AlphaPixelB/255*BGPixelB
Else
  ResultPixelR=BGPixelR
  ResultPixelG=BGPixelG
  ResultPixelB=BGPixelB
EndIf
Müßte man mal ausprobieren, ob mit dieser Routine ähnliche Ergebnisse entstehen. Bin grad zu faul, das sofort zu tun. Auf dem Internetrechner ist kein PureBasic installiert.
Als Alphasprite gehen lt. Dokumentation immer nur GraustufenBilder ..und da ist die 128te Stelle ein 128er Graustufenwert, oder?
Vermute ich auch, aber man müßte mal genauer schauen, wie das BMP-Format da aussieht, ob es einen spezifischen Graustufen-Modus kennt oder Graustufenbilder einfach als 8-Bit-Bild mit irgendeiner Palette speichert, die dann eben nur Grauwerte enthält.
sire
Beiträge: 10
Registriert: 25.11.2005 02:09

Beitrag von sire »

Kleine Korrektur: Ich habe mittlerweile entdeckt, daß der angeblich bei 149 liegende Wert für die immer volle Transparenz eine Fehlmessung war. Aus irgendeinem Grund hat Photoshop das so angezeigt. In Wirklichkeit verhalten sich die Alpha-Sprites bei mir also doch so wie dokumentiert.
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

Hätte mich eigentlich auch gewundert.

hab das Aplphaimage mal geändert ..
hier nebst neuem Code.
Irgendwie hat das was mit 380 zu tun.
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Beitrag von RSBasic »

Hallo :)
Ich beschäftige mich mit Schatten/Licht in 2D.
Da soll diese Alpha-Techniik gut sein.
Anstatt ich ein neuer Thread eröffne, mache ich hier weiter.
Also ich habe eine Frage.

@bobobo
Kannst du deine Datei (wenn du sie noch hast) hochladen?
Wenn nicht, gibt es nen guten Source, wo gezeigt wird, wie man mit ChangeAlphaIntensity und DisplayAlphaSprite umgehen kann?
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Wenn du den Algho selber schreiben willst, musst du dich entscheiden, ob du auf richtige Alphakanäle (wie PNG) oder auf AlphaSprites umsteigen willst.

Bei einem Float-Alphawert ist die Formel für den Rot-, Grün- und Blau-Kanal beim Überblenden von Pixel:

Code: Alles auswählen

Destination = (Source * SourceAlpha) + (Mix * MixAlpha)
Mix = Farbe fürs Draufblenden
MixAlpha = Transparenz des Mischpixels
SourceAlpha = Transparenz des Quellpixels
Destination = Farbe, die im nachhinein rauskommt

Wenn du einen Screenbuffer hast, dessen Pixel KEINE Transparanz haben können, dann ist

Code: Alles auswählen

SourceAlpha = 255 - MixAlpha
MixAlpha ist (logischweise) die Transparenz des zu blenden Pixels. Ansonsten solltest du SourceAlpha nicht neu ausrechnen, sondern einfach neu verwenden (vorherigen Alpha-Wert im Screenbuffer wieder nehmen). Wenn du mit Überblendung arbeitest, wo beide Farben (Quell- und Misch-Farbe) einen Alphawert von 1 haben, dann sollte DestinationColor besser im WORD-Format sein, da so übergroße Farbwerte abgefangen werden können. Z.B. wenn du als Quellfarbe $FF FF FF FF und als Mischfarbe $FF FF FF FF hast, dann würde das für jeden Farbkanal einen Wert von 512 ergeben, lässt sich ja schlecht in einem Character/Byte abspeichern ;) . Daher einfach überprüfen und den Wert korrigieren (kannste wie gesagt weglassen, wenn nur dein Mischwert Transparenz hat und Quellwert keine).
Antworten