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

the[V]oid

Alter Hase

  • »the[V]oid« ist der Autor dieses Themas

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

1

17.05.2009, 14:30

[OpenGL] Texturen

Nach langer Zeit wollte ich nochmal etwas mit OpenGL machen... und bin beim Laden von Texturen auf ein Problem gestoßen. Zum Verwalten von Texturen habe ich die folgende Klasse geschrieben:

C-/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
class Texture
{

    private:

        Texture (const GLuint nTextureID) : m_nTextureID (nTextureID) { }


    public:

        ~Texture () { glDeleteTextures (1, &m_nTextureID); }


    public:

        static Texture* loadFromBMP (const std::string& sFile);

        GLuint getID () const
        {
            return m_nTextureID;
        }

        void setActive () const
        {
            glBindTexture (GL_TEXTURE_2D, m_nTextureID);
        }


    private:

        const GLuint m_nTextureID;

};


Die Funktion zum Laden der Textur ist wie folgt definiert:

C-/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
Texture* Texture::loadFromBMP (const std::string& sFile)
{
    std::ifstream fIn (sFile.c_str (), std::ios::in | std::ios::binary);
    if (fIn.good ())
    {
        try
        {
            // read header

            unsigned short nFormat;
            fIn.read (reinterpret_cast <char*> (&nFormat), 2);
            if (nFormat != 19778)
            {
                std::cerr << "(EE) Failed to read: " << sFile << std::endl;
                std::cerr << "(EE)   Not a Windows Bitmap." << std::endl;
                std::cerr << std::endl;
                fIn.close ();
                return NULL;
            }

            fIn.seekg (18);
            signed int nWidth, nHeight;
            fIn.read (reinterpret_cast <char*> (&nWidth), 4);
            fIn.read (reinterpret_cast <char*> (&nHeight), 4);

            // compute body size

            const unsigned int nBodySize = 3 * nWidth * nHeight;

            // read planes

            unsigned short nPlanes;
            fIn.read (reinterpret_cast <char*> (&nPlanes), 2);

            // read bits per pixel

            unsigned short nBPP;
            fIn.read (reinterpret_cast <char*> (&nBPP), 2);

            // ensure format is supported

            if (nPlanes != 1 || nBPP != 24)
            {
                std::cerr << "(EE) Failed to read: " << sFile << std::endl;
                std::cerr << "(EE)   Unsupported format: " << nBPP << " bpp, " << nPlanes << " plane(s)" << std::endl;
                std::cerr << "(EE)   Only bitmaps with 24 color depth and 1 plane are supported." << std::endl;
                std::cerr << std::endl;
                fIn.close ();
                return NULL;
            }

            // seek past the rest of the header

            fIn.seekg (54);

            // read body data

            char* const pcData = new char [nBodySize];
            fIn.read (pcData, nBodySize);

            // we are done reading the file

            fIn.close ();

            // reverse byte order (convert 'BGR' to 'RGB')

            for (unsigned int j = 0; j < nBodySize ; j += 3)
            {
                pcData [j] ^= pcData [j + 2];
                pcData [j + 2] ^= pcData [j];
            }

            // now we need to create the texture

            GLuint nTextureID;
            glGenTextures (1, &nTextureID);
            glBindTexture (GL_TEXTURE_2D, nTextureID);
            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

            // 2D texture, level of detail 0 (normal), 3 components (red, green, blue), x size, y size,

            // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself

            glTexImage2D (GL_TEXTURE_2D, 0, 3, nWidth, nHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pcData);
            delete [] pcData;

            // finish

            return new Texture (nTextureID);
        }
        catch (...)
        {
            fIn.close ();
            std::cerr << "(EE) Failed to read: " << sFile << std::endl;
            std::cerr << "(EE)   Unknown error." << std::endl;
            std::cerr << std::endl;
            return NULL;
        }
    }
    else
    {
        fIn.close ();
        std::cerr << "(EE) Failed to read: " << sFile << std::endl;
        std::cerr << "(EE)   Either file not found or not allowed to open for reading." << std::endl;
        std::cerr << std::endl;
        return NULL;
    }
}


Nun rufe ich bei der Initialisierung des Programms auf:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static Texture* s_aTextures []; // Member einer Klasse C


// [...]


Texture* C::s_aTextures [] = { NULL, NULL, NULL, NULL, NULL, NULL };

// [...]


s_aTextures [0] = Texture::loadFromBMP ("test1.bmp");
s_aTextures [1] = Texture::loadFromBMP ("test2.bmp");
s_aTextures [2] = Texture::loadFromBMP ("test3.bmp");
s_aTextures [3] = Texture::loadFromBMP ("test4.bmp");
s_aTextures [4] = Texture::loadFromBMP ("test5.bmp");
s_aTextures [5] = Texture::loadFromBMP ("test6.bmp");


Beim Vor-Rendern der Szene in eine Display-List rufe ich dann auf unterschiedlichen Elementen des Arrays auf:

C-/C++-Quelltext

1
s_aTextures [2] -> setActive ();


Nun das Problem: Alles, was ich rendere, wird mit derselben Textur belegt, obwohl ich unterschiedliche Texturen einstelle. Um genau zu sein, wird alles mit der Textur überzogen, die ich als letztes erstelle (lade) - Nicht missverstehen, es wird nicht immer die Textur benutzt, auf der ich zuletzt setActive aufrufe. Aber ich finde den Fehler einfach nich. Die lokale Variable nTextureID in Texture::loadFromBMP hat auch einen korrekten Wert, nämlich bei jedem Aufruf einen anderen. Jemand eine Idee?

Danke im Voraus
<< an dieser Stelle ist eine Signatur verstorben >>

K-Bal

Alter Hase

Beiträge: 703

Wohnort: Aachen

Beruf: Student (Elektrotechnik, Technische Informatik)

  • Private Nachricht senden

2

17.05.2009, 15:03

C-/C++-Quelltext

1
2
// read body data

            char* const pcData = new char [nBodySize];


Schon einmal ohne das const probiert?

Warum beschäftigst du dich eigentlich mit OpenGL anstatt unsere Aufgaben für die Uni zu rechnen :badgrin: Ist aber schon okay, habe die letzte Aufgabe hinbekommen ;)

the[V]oid

Alter Hase

  • »the[V]oid« ist der Autor dieses Themas

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

3

17.05.2009, 15:09

Zitat von »"K-Bal"«

Schon einmal ohne das const probiert?

Bis jetzt grade nicht, aber wie erwartet ändert das nichts... Warum sollte der Pointer auch seinen "Adressaten" ändern?

Zitat von »"K-Bal"«

Warum beschäftigst du dich eigentlich mit OpenGL anstatt unsere Aufgaben für die Uni zu rechnen :badgrin: Ist aber schon okay, habe die letzte Aufgabe hinbekommen ;)

Wolllt ich grade mit anfangen ;)
<< an dieser Stelle ist eine Signatur verstorben >>

K-Bal

Alter Hase

Beiträge: 703

Wohnort: Aachen

Beruf: Student (Elektrotechnik, Technische Informatik)

  • Private Nachricht senden

4

17.05.2009, 15:55

Zitat von »"the[V«

oid"]

Zitat von »"K-Bal"«

Schon einmal ohne das const probiert?

Bis jetzt grade nicht, aber wie erwartet ändert das nichts... Warum sollte der Pointer auch seinen "Adressaten" ändern?


Ähm du änderst ja nachher unten in einer for-Schleife den Speicherbereich, deswegen ist mir das aufgefallen.

Ich denke mal, dass das Problem irgendwie daher kommt, dass du zwar immer neue Texturen erstellst, aber deren interne Zeiger immer auf den gleichen Speicherbereich zeigen.

the[V]oid

Alter Hase

  • »the[V]oid« ist der Autor dieses Themas

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

5

17.05.2009, 15:59

Zitat von »"K-Bal"«

Zitat von »"the[V«

oid"]

Zitat von »"K-Bal"«

Schon einmal ohne das const probiert?

Bis jetzt grade nicht, aber wie erwartet ändert das nichts... Warum sollte der Pointer auch seinen "Adressaten" ändern?


Ähm du änderst ja nachher unten in einer for-Schleife den Speicherbereich, deswegen ist mir das aufgefallen.

Ich denke mal, dass das Problem irgendwie daher kommt, dass du zwar immer neue Texturen erstellst, aber deren interne Zeiger immer auf den gleichen Speicherbereich zeigen.


Eine Textur wird ja durch nicht mehr als eine ID repräsentiert, durch die sie im Speicher der Grafikkarte angesprochen wird. Und diese ID ist jedes mal anders (überprüft). Die eigentliche Textur wird ja mittels glTexImage2D im Grafikspeicher abgelegt, das habe ich auch überprüft, in dem ich direkt nach diesem Aufruf den gesamten Speicherbereich von pcData mit 0 überschrieben habe - Würden die Daten dann immernoch aus dem Systemspeicher bezogen werden, hätte ich bestimmt keine Textur im gerenderten Bild gesehen, was ich aber tat ;)
<< an dieser Stelle ist eine Signatur verstorben >>

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

6

18.05.2009, 11:59

Wie sieht denn der Rendercode aus?

the[V]oid

Alter Hase

  • »the[V]oid« ist der Autor dieses Themas

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

7

18.05.2009, 17:32

Ja, in der Render-Routine lag der Fehler... wusste nicht, dass man nicht Texturen innerhalb eines begin-end-Blocks wechseln kann.
<< an dieser Stelle ist eine Signatur verstorben >>

8

18.05.2009, 21:58

begin und end sollte man sowieso nur für Testzwecke benutzen und sobald es geht dann ersetzen.
Lieber dumm fragen, als dumm bleiben!

sgaffga

Frischling

Beiträge: 6

Wohnort: Krefeld

  • Private Nachricht senden

9

19.05.2009, 22:48

Mir ist grad noch etwas aufgefallen:

Du hast eine Inkonsistenz in deiner Texturklasse: Du löscht im
Destruktor den Namen der Textur obwohl dieser im Konstruktor nicht
erzeugt wurde - d.h du gibst etwas frei das dir nicht gehört ;)

Grüße
Stefan

Werbeanzeige