Surface - Alphawerte

  • GM 8

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Surface - Alphawerte

    Hallo Leute!

    Ich bin vor geraumer Zeit auf ein Problem gestossen dass sich nicht so leicht lösen lässt.
    Es geht um Surfaces die Alphatransparenzwerte beinhaltet.

    Diejenigen von euch die mit Surfaces gearbeitet haben wissen sicher, das Funktionen wie Surface_copy die Surfaces zwar ordnungsgemäß behandeln, die Alphatransarenzwerte werden jedoch verfälscht bzw garnicht übernommen.

    So ist es z.B: vorgekommen dass sich beim zeichnen eines Transparenten Sprites, die Farben auf einmal bleicher wurden. (Konnte das Problem kurzzeitig aber iwie mithilfe von Blendmodes umgehen...)
    Generell war es so dass ich viele Probleme mit Surfaces und Transparenzen hatte. (Insbesondere das Kopieren einer Surface.)

    Meine Frage an euch:

    - Ist es möglich Surfaces mit Alphawerten zu kopieren, ohne Verluste bei den Alphawerten zu bekommen? (Bei mir zumindest wurden die Farben nach dem Kopieren und zeichnen der Kopierten Surface bleicher bzw dünkler.)
    - Hattet ihr auch Probleme mit Alphawerten auf Surfaces? Wenn ja: Welche Tipps habt ihr für mich um evtl. Problemen aus dem Weg zu gehen?

    Wäre für jede Form von Hilfe dankbar.

    mfg

    LEWA

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von LEWA ()

  • Das mit dem "zeichnen" der Surface auf die andere habe ich schon gemacht.
    Anstatt also einfach zu kopieren, überschreibe ich die surface mit "leere" (sodass alles gelöscht wird) und zeichne eine andere Surface darauf. (ist sozusagen ein eigener "surface_copy" script.)

    Hat aber dennoch nichts gebracht. Bin letztens an genau diesem Problem verzweifelt. :S

    Benutze jedoch immernoch den GM 8.0 (da mir 8.1 aktuell vieeel zu verbuggt ist. X( )
    Habe also keine Ahnung ob im 8.1er das Handling der surfaces im Bereich Alphatransparenz verbessert wurde.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von LEWA ()

  • ja das finde ich auch (mit game Maker 8.1)

    oder versuch es mit BlendMode bm_add auf das andere Surface zu zeichnen, bei mir hatte es nämlich mit mehrstufigem schatten viel gebracht.

    Willst du damit das wasser transparent zeichnen?
    ////////////////////////////////////////////////////////////////////////////////////////////////
  • Jop. Wasser und Glas sollen transparent gezeichnet werden.

    Dies ist jedoch aktuell aufgrund der Surfaces nicht möglich. Ich habe auch versucht etliche Blendmodes zu verwenden. > Hat alles nichts gebracht.
    Sobald ich die eine Surface auf die andere "zeichne" kommen diese eigenartigen transparency bugs. :(


    Hier mal der Code den ich dafür benutze:

    GML-Quellcode

    1. var temp_surface;
    2. var surf;
    3. surf = block_surface_mid;
    4. temp_surface=surface_create(obj_controller.map_w_blocks*16*5,obj_controller.map_h_blocks*16); //5 Chunks -1 unnötiges =4 Chunks die übertragen werden müssen.
    5. //kopiere die surface in die temporäre surface (mit der Verschiebung aufgrund der Chunks)
    6. surface_set_target(temp_surface);
    7. draw_surface(surf.sur_main,map_w_blocks*16,0);
    8. surface_reset_target();
    9. //lösche nun die main Surface des Spiels und zeichne die verschobene Surface rein
    10. surface_set_target(surf.sur_main);
    11. draw_clear_alpha(c_white,0);
    12. draw_surface(temp_surface,0,0);
    13. surface_reset_target();
    14. //lösche die temporäre surface
    15. surface_free(temp_surface);
    Alles anzeigen


    Das müssen irgendwelche Internen Fehler im GM sein. Anders kann ich es mir nicht erklären. :(
  • theoretisch müsste eigentlich alles klappen...
    vielleicht ist das wirklich einer dieser uncoolen GM-Geschichten, bei denen der Code macht, was er will.

    umständlicher wäre es, wenn du zwei surfaces, getrennt Wasser und Glas zeichnest.
    ODER...
    du zeichnest die Objekte ganz normal auf die Surface und dann die Surface transparent...
    noch ne möglichkeit wäre, dass er die variable surf als das Objekt surf erkennt und damit mist macht...




    aber ich lasse mich gerne eines besseren belehren (weil ich sonst auch scon mit einer Surface genug Probleme habe...)
    ////////////////////////////////////////////////////////////////////////////////////////////////
  • Die Objekte erkennt er ohne Probleme. (Habe das extra in einem eigenen GM-File getestet.)
    Er übeträgt alles bis auf die transparenzen.

    Über 2 Surfaces (eine für Transparente und eine für ncihtrtransparente Blöcke) habe ich zwar nachgedacht, jedoch würde das Spiel dann vieel zu unübersichtlich werden.
    Ich habe 5 Chunks von denen jedes 5 Surfaces besitzt: Vorder, Hinter und Mittlere Ebene. Die vordere und Hintere Ebene haben noch zusätzliche Shadingebenen.
    5*5 = 25 Surfaces. Wenn ich noch zu jeder ebene eine Transparente Ebene hinzufügen würde, würde der Ressourcenverbrauch erheblich steigen.

    Noch dazu würde dann Glas und Wasser die gleiche Transparenz besitzen. Dies ist also auf keinen Fall eine Lösung für mich.
    Die Transparenzen sollen von den Sprites die ich draufzeichne übernommen werden. Nicht vom Code definiert werden.

    Eine andere Möglichkeit für das darstellen von vielen Blöcken gibt es nicht. Objekte sind viel zu langsam, Tiles verbrauchen zwar weniger Speicherplatz (solange sie statisch sind...) wenn es aber um das Platzieren bzw löschen von Tiles (in realtime) geht, kommt man schnell an Performancegrenzen. Surfaces sind die schnellste und beste Alternative. Jedoch gibt es da eben diese Probleme mit Transparenzen.
  • Ich kann wirklich nicht sagen, denn so funktionierts:

    GML-Quellcode

    1. surface_set_target(surf);
    2. draw_clear_alpha(c_white,0);
    3. draw_sprite(sprite0,0,mouse_x,mouse_y);
    4. surface_reset_target();
    5. surface_copy(copy,0,0,surf);
    6. draw_surface(copy,0,0);



    Da kommt raus:
  • Nein, funktioniert leider nicht.

    Das Problem fängt schon beim zeichnen der Sprites AUF die Surface an.
    Dabei verblassen bzw Verdunkeln sich die Farben.

    Hier ein kleines Bild was mein Problem visuell darstellt:


    Links seht ihr die externe Datei die in den GM geladen wurde. (diese beinhaltet noch die Korrekten Transparenzen der Farben). Rechts sind die verfälschten Werte.

    Das Bild wird hierbei in 16*16 Pixel unterteilt. Jeder dieser Ausschnitte wird einem neuen Sprite zugewiesen.
    Diese Sprites werden nun nacheinander auf eine 2te Surface (RECHTS) gezeichnet. Hierbei verfälschen sich jedoch die Alphatransparenzen.
    Wieso dies passiert weiss ich nicht.

    Der gleiche Effekt taucht auch auf wenn ich eine Surface mit Alphatransparenzen auf eine andere kopieren will.


    Ihr könnt euch die Datei ebenso hier noch runterladen (.gmk) und selber herumprobieren. Evtl findet jemand des Rätsels Lösung.
    Dateien

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von LEWA ()

  • So, dieses Example sollte helfen.

    Wie funktioniert's?
    Als erstes wird der Sprite + Alphamask (ein graues Bild, das die Alphawerte präsentiert) ins Spiel geladen.
    Danach werden alle Surfaces mithilfe von (wie von Chaos Creator bereits erwähnt) draw_clear_alpha(c_white,0) komplett geleert.
    Dann werden (wie in der alten gmk) die zwei for Schleifen durchlaufen und die Sprites in den Speicher gehauen.
    Am Ende wird die Surface lediglich kopiert. (Kein Zeichnen mehr in den for schleifen nötig).

    LEWA schrieb:

    [...] das Funktionen wie Surface_copy die Surfaces zwar ordnungsgemäß behandeln, die Alphatransarenzwerte werden jedoch verfälscht bzw garnicht übernommen.

    Wie soll man Alphawerte kopieren, wenn sie garnicht existieren? :P

    LEWA schrieb:

    So ist es z.B: vorgekommen dass sich beim zeichnen eines Transparenten Sprites, die Farben auf einmal bleicher wurden.

    Das lag am Hintergrund, der immer mitkopiert wurde. (edit: weil die Surface nicht geleert wurde! :D)

    Ich hoffe ich konnte helfen
    -Tobi97
    Dateien
  • Die Alphatransparenzen sind/waren da. Die Farben die ich in die tiles reingemalt habe (bis auf das Violette gitter...) hatten unterschiedliche Alphawerte. (einfach mit gimp oder Paint öffnen.)

    Das gefixte Example funktioniert aber nicht ordnungsgemäß. (siehe Screenshot)



    Wieso ladest du eigentlich eine Alphamaske rein? PNG Bilder besitzen doch von Haus aus Alphakanäle.

    Und wie genau soll sich der Hintergrund Mitkopiert haben? Wird etwa bei "sprite_create_from_surface" der Hintergrund (Hinter der Surface) auch übernommen?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von LEWA ()

  • LEWA schrieb:


    Das gefixte Example funktioniert aber nicht ordnungsgemäß. (siehe Screenshot)

    Genau so sollte es doch sein.
    Rechts ist die fertige Surface und die Sprites haben auch die Alphawerte (hoffe ich zumindest).

    LEWA schrieb:


    Wieso ladest du eigentlich eine Alphamaske rein? PNG Bilder besitzen doch von Haus aus Alphakanäle.

    Ich weiß, komischerweise hat es ohne Alphamasken ned funktioniert (keine Ahnung, warum ned)

    LEWA schrieb:


    Wird etwa bei "sprite_create_from_surface" der Hintergrund (Hinter der Surface) auch übernommen?

    Nein, aber der Hintergrund der Surface.
    (Der wurda ned mit draw_clear_alpha(c_white,0) gelöscht )
    Allerdings ist es mir ein Rätsel, warum der ned gleich von surface_create(...); gelöscht wird.

    -Tobi97
  • Eigentlich sollte dies (wie bei deinem gefixten example) nicht ausschauen.

    Die Sprites sollen GENAU SO ausschauen (also von den farben und Alphawerten her) wie sie original als Gesamtbild in den GM geladen wurden.
    Bei dir (siehe Bild im Spoiler) werden die Sprites auf der Surface nicht korrekt angezeigt. (Zwar besser als bei mir, aber so wie das linke Original-tileset schaut es noch nicht aus.)

    Verstehst du mein Problem? Die Sprites die (rechts) auf die Surface gezeichnet wurde, verblassen oder verfälschen sich. Ich möchte jedoch dass dies nicht passiert.

    Kurzgesagt: Das Linke tileset (im Example) soll dem Rechten 1:1 gleichen. (hinsichtlich Farben und transparenz.)

    Der Unterschied ist nur der, dass links das eigentliche Tileset geladen wurde, und rechts sind einfach die einzelnen Sprite-Tiles auf eine eigene Surface gezeichnet worden, die aus dem linken tileset (per sprite_create_from_surface) vom linkem entnommen wurden.
  • LEWA schrieb:

    Verstehst du mein Problem? Die Sprites die (rechts) auf die Surface gezeichnet wurde, verblassen oder verfälschen sich. Ich möchte jedoch dass dies nicht passiert.

    Übrigens ist links nur das Bild ohne Alphachannels.
    Rechts ist das Bild, aus den Sprites (um Rechenleistung zu sparen, werden die ned einzeln im Create Event gedrawd, sondern die alte Surface kopiert)
    Die Sprites sehen also aus, wie im rechten Bild mit Alphachannels und die Farben verfälschen sich nur, weil sie teilweise transparent sind und mit dem Hintergrund verschmelzen (änder mal die Hintergrundfarbe z.B.).

    -Tobi97
  • Asooo. hab darauf garnicht geachtet. Dachte das linke Tileset hätte bereits die Transparenz. :D

    Blos eine Frage hätte ich da noch:
    Gibt es eine Möglichkeit denselben "behalt die Transparenz und verfäklsche nichts" Effekt OHNE das löschen der gesamten Surface (mit draw_clear) zu verursachen?
    Der Hintergedanke dahinter ist nähmlich der dass ich während der Laufzeit jederzeit einen Block platzieren und wieder löschen kann.

    Wenn ich jedoch draw_clear anwede, löscht er mir den komplett gezeichneten Raum. (Also alle Blöcke.) Hier wäre z.B: eine draw_clear funktion Hilfreich die nur einen bestimmten Bereich der Surface löscht. (also z.B: es löscht ein rechteck mit 16*16 Pixel größe.)

    Gebe es in dieser Richtung eine Möglichkeit?
    Ich frage jetzt deshalb so noobhaft, da ich gerade am packen bin und morgen wegfahren muss. No time für das ausprobieren am GM. :D (und ne Internetverbindung werde ich für längere zeit auch nicht haben sodass ich jetzt eine ungefähre Lösung haben muss. XD)
  • Ganz einfach:

    GML-Quellcode

    1. surface_set_target(deine_surface);
    2. draw_set_blend_mode(bm_subtract);
    3. draw_set_color(c_black);
    4. draw_rectangle(x1,y1,x2,y2);
    5. draw_set_blend_mode(bm_normal);
    6. surface_reset_target();


    Dadurch wird nur die Stelle des Rechtecks gelöscht. Wenn du was hinzeichnest, kannst du es einfach draufzeichnen, musst nur aufpassen, dass das entsprechende Feld leer ist.