Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

1

25.05.2012, 10:55

Transparenz bei OpenGL/SDL

Hi.
Ich arbeite der Zeit an einem Uni Projekt. Ich soll einen Körper darstellen durch den später verschiedene Prozesse modelliert werden. Zum Anfang ganz gewöhnliche Blutkörperchen die durch die Adern gepumpt werden.
Also habe ich mir ein Tileset gesucht und mit Tiled eine entsprechende "Map" erstellt.
Hier mal der Link zur fertigen Map, wie sie in Tiled zu sehen ist und später eben auch im Fenster dargestellt werden sollte: http://s14.directupload.net/file/d/2897/9nb4jx29_png.htm
Und gleich anbei mein gefundenes Tileset: http://s14.directupload.net/file/d/2899/2662a3wu_png.htm
Die von Tiled erstelle .tmx Datei habe ich nun eingelesen und untersucht. Mein Programm ermittelt dann die genutzten Tiles, schneidet die aus dem, zugegeben, großen Tileset aus und bastelt sich so ein neues, kleineres Tileset zusammen, da man ja in den meisten Fällen nicht alle Tiles braucht. So dachte ich mir, spart man sich eine übergroße Textur, die man immer wieder binden muss.
Soweit so gut. Nun scheint es aber, dass die Transparenz nicht übernommen wird (hier mal mein neues, automatisch erstelltes Tileset: http://www.bilder-hochladen.net/files/jlqo-1-c4ca-png.html) denn ich bekomme statt obiger Map, diese Map (http://s14.directupload.net/file/d/2897/mjouqppg_png.htm) mit lauter hübschen schwarzen Rändern. Höchst unschön.

Ich sitze an dem Problem nun seit inzwischen 2 1/2 Tagen und habe bisher versucht die Farbdaten aus den übertragenen Pixels zu holen und die schwarzen transparent zu machen, sprich ihr Alpha Value auf 0 zu setzen. Klappte aber nicht wie erhofft, denn die waren bereits auf 0.
Ebenso hatte ich mit glBlendFunc und glAlphaFunc herum experimentiert (Experimentiert da ich in einigen Bereichen immer noch frischer OpenGL Neuling bin, oder mir zumindest so vorkomme). Auch habe ich hab' ich versucht die Masken beim Erstellen der SDL Surface zu verändern - allerdings auch ohne sichtbaren Erfolg.
Ich hoffe, dass einer von euch eine Lösung weiß, wie man den Alpha Kanal korrekt übernimmt oder wie man ihn wieder reaktiviert.

Hier mal mein Code zum erstellen der neuen SDL Surface (Ich nutze im übrigen SDL 2.0):

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Surface Create(ushort width, ushort height, ubyte deepth) {
    assert(deepth >= 8 && deepth <= 32);

    this.Free();

    this._surface = SDL_Check(SDL_CreateRGBSurface(
        0,
        width, height,
        deepth,
        0, 0, 0, 0
    ));

    return this;
}


Den OpenGL Code zum Rendern spare ich mir erstmal, eig. sollte er korrekt sein. Im Grunde passiert auch nichts spannendes, ich buffere die Vertex und Textur Koordinaten in der "Load" Funktion und binde die Textur später und Zeichne den Buffer mit glDrawArrays in der "Draw" Methode. Ich habe auch schon versucht, die Daten umgedreht einzulesen, doch dann bekam ich diese Ausgabe: http://s14.directupload.net/file/d/2900/5fnwzr5z_png.htm
Die unteren Bilder verdecken dann eben die oberen, was zwar zu keinen schwarzen Rändern führt, aber trotzdem keine Lösung ist.^^

Hat jemand eine Idee?
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

25.05.2012, 12:38

Mich würde dabei interessieren, was Du als depth ("deepth") übergibst. Wahlweise wäre das "Ausschneiden" sicher interessant, weil ich mir gut vorstellen kann, dass Du dabei aus einem transparenten Surface in ein schwarzes kopierst, was dann natürlich in schwarzem Hintergrund resultiert.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

3

25.05.2012, 13:02

Der gesamte kommentierte Lade Code:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
*
*/
void Load(string file = "") {
    if (file.length > 0) {
        this._tmr.Read(file);
    }
    
    // Tileset Objekt erstellen
    Surface tileset = new Surface();

    const string tileset_file = strip(this._tmr.GetTilesetFile());
    // Tileset laden
    tileset.LoadFromFile(tileset_file);

    const ushort tw = this._tmr.GetTileWidth();
    const ushort th = this._tmr.GetTileHeight();
    const ushort tiles_each_line = cast(ushort)(tileset.Width / tw);

    Surface[ushort] tiles;

    ushort count = 0;

    Rect tile_rect = new Rect(0, 0, tw, th);
    
    // Die Positionen der Tiles innerhalb des Tiles errechnen (mit den Daten aus der .tmx Datei)
    foreach (const Tile t; this._tmr.GetTiles()) {
        if (t.Gid !in tiles) {
            const ushort[2] pos = CalcPos(t.Gid, tiles_each_line, tw, th);
            
            // Position des Rect's setzen
            tile_rect.SetPosition(pos[0], pos[1]);
            
            // Subsurface speichern, mit seiner ID
            tiles[t.Gid] = tileset.SubSurface(tile_rect);

            ++count;
        }
    }
    
    // Größe des neuen Tileset errechnen
    ushort size = 2;
    while (size < count) {
        size *= 2;
    }
    
    if (size > 2) {
        size = cast(ushort) floor(sqrt(cast(float) size));
    }

    writefln("count: %d, size: %d", count, size);
    
    // Größe mal Tile Breite und Höhe
    const ushort w = cast(ushort)(size * tw); // (count > 2 ? size : count)
    const ushort h = cast(ushort)(size * th);

    writefln("w: %d, h: %d", w, h);
    
    // Neues Tileset erstellen
    Surface new_tileset = new Surface();
    new_tileset.Create(w, h, 32);

    ushort line, column;

    //Rect clip = new Rect(0, 0, tw, th);
    tile_rect.SetPosition(0, 0);

    this._vtable.clear();
    
    // Tileset befüllen mit den notwendigen Tiles
    foreach (ushort gid, Surface tile; tiles) {
        new_tileset.Blit(tile, tile_rect);

        this._vtable[gid] = [tile_rect.x, tile_rect.y];

        column++;
        if (column >= size) {
            column = 0;

            line++;
        }

        const ushort rx = cast(ushort)(column * tile_rect.Width);
        const ushort ry = cast(ushort)(line * tile_rect.Height);

        //writefln("rx: %d, ry: %d", rx, ry);

        tile_rect.SetPosition(rx, ry);
    }
    /*
    new_tileset.SetAlphaMod(0);
    new_tileset.SetBlendMode(Surface.BlendMode.Multiply);
    */
    
    // gucken was ich da fabriziert habe
    new_tileset.SaveToFile("img/Tiled/new_tileset.png");

    Texture.Format fmt;
    if (new_tileset.IsMask(Surface.Mask.Red, 0x000000FF)) {
        fmt = Texture.Format.None;
    } else {
        fmt = (new_tileset.CountBytes() == 4) ? Texture.Format.BGRA : Texture.Format.BGR;
    }

    //writefln("CountBits: %d", new_tileset.CountBits()); // 32

    this._tex.LoadFromPixels(new_tileset.GetPixels(), w, h, new_tileset.CountBits(), fmt);
    //this._tex.CreateMaskFromColor(Color.Black.Modify(Color.Spectrum.Alpha, 0), 255);

    this._need_update = true;
}


Ich schätze mal bei Zeile 35 und/oder Zeile 72 tritt der besagte Fehler auf, also das er ins schwarze Rendert.

edit:
Ja es liegt eindeutig daran. Die Tiles werden auf ein schwarzes Bild geblittet und die Schwarze ist irgendwie nicht weg zubekommen.
Weißt jemand wie oder ob das geht?
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Architekt« (25.05.2012, 14:12)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

25.05.2012, 14:57

Zur letzten Frage kann ich nichts sagen, ich kann aber leider nicht an mich halten: Kommentare sind Code-Smell. Code sollte für sich selbst-sprechend sein und Kommentar muss nur dann eingesetzt werden, wenn er es nicht ist, was aber dann müffelnder Code und der Kommentar nur Deodorant wäre. Da der Code bei Dir völlig ok (nur leider die Methode etwas sehr lang) ist, hast Du unnötig Deo verwendet ;)
(Code-Kommentare sind nicht zu verwechseln mit Dokumentation. Letzteres ist sogar *sehr* sinnvoll.)

Bei der Erstellung durch "new Surface()", wird da ein RGBA-Surface erstellt oder nur ein RGB-Surface?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (25.05.2012, 15:02)


Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

5

25.05.2012, 14:59

Nun, ich dachte ich mache euch das Leben etwas einfacher, wenn ich direkt dazu schreibe, was passiert. Aber ok, merk ich mir. :) Dokumentation folgt, wenn ich endlich mal heraus finde, wie man in SDL Transparente Surfaces erstellt.
Per Colorkey funktioniert das ganze leider nicht. :/
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

25.05.2012, 15:03

Siehe edit:

Bei der Erstellung durch "new Surface()", wird da ein RGBA-Surface erstellt oder nur ein RGB-Surface?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

7

25.05.2012, 15:09

Die Create Funktion der Surface Klasse sieht so aus:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Surface Create(ushort width, ushort height, ubyte depth) {
    assert(depth >= 8 && depth <= 32);

    this.Free();

    this._surface = SDL_Check(SDL_CreateRGBSurface(
        0,
        width, height,
        depth,
        0, 0, 0, 0
    ));

    return this;
}

Laut dieser Doku sollte der default Wert der Masken ausreichen.
Ich habe aber bereits sowohl

rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
als auch
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;

bereits probiert. Ändert leider überhaupt nichts. Vllt. weil das originale Tileset ein BGRA Bild ist?

Jedenfalls bleibt das ganze bisher immer schwarz, ich kann es auch mit einer anderen Farbe füllen, aber dann ist die eben Sichtbar.
Und wie du siehst spricht der Funktionsname eher für "RGB", aber die Parameter eig. deutlich für RGBA.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

25.05.2012, 15:25

Und der Alpha-Wert muss bei was liegen? Bei 0 oder bei 0xFF? Denn ich schätze mal das wird alles mit 0 initialisiert, was aber eventuell eben falsch ist. Die Masken werden daran nix ändern, aber wie man die Initialwerte rein bekommt, das kann ich Dir leider nicht sagen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

9

25.05.2012, 15:27

Naja afaik bei 0, wegen komplett transparent.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

25.05.2012, 15:28

Heißt 0 denn auch wirklich komplett transparent und nicht komplett opak?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige