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

Phili

unregistriert

1

02.08.2006, 20:48

Texturen aus bmp-Dateien ohne D3DX laden

Langsam bekomm ich Routine mit den Tutorials :D . Ich werde auch diesmal eine eher leichte Frage bearbeiten, die allerdings Einsteigenrn sicher was nützen wird: Wie lade ich eine Textur aus einer bmp-Datei ohne D3DX?
Im Grunde ist das ziemlich einfach, mit diesem Tutorial ist es aber sicher noch einfacher :D .
Die Datei muss 24bit Farbtiefe haben und unkomprimiert sein-das ist fast immer der Fall. Außerdem muss die Breite eine Potenz von 2 sein(also 2, 4, 8, 16, ..., 256, 512)-alles andere ist in der Spieleprogrammierung eh nicht besonders sinnvoll, deswegen können wir mit diesen Einschränkungen wirklich gut leben.
Also, erstmal müssen wir wissen, wie eine bmp-Datei aufgebaut ist.
Am anfang kommt der Header, den wir als Struktur anlegen wollen:

C-/C++-Quelltext

1
2
3
4
5
6
7
struct PH3DBitmapHeader
{
    WORD bfType;         //zeichenkette BM

    DWORD bfSize;        //Größe der Datei-meistens unbrauchbar

    DWORD bfReserved;//unwichtig

    DWORD bfOffbits;    //begin des eigentlichen Bildes in Bytes vom Dateianfang

};

Dann kommt der Info-Header, der meistens 40 Bytes lang ist:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct PH3DBitmapInfo
{
    DWORD biSize;          //Größe des Informationsblocks

    LONG biWidth;           //Breite des Bildes

    LONG biHeight;          //Höhe des Bildes

    WORD biPlanes;       
    WORD biBitCount;
    DWORD biCompression; 
    DWORD biSizeImage; 
    LONG biXPelsPerMeter;  
    LONG biYPelsPerMeter; 
    DWORD biClrUsed;
    DWORD biClrImportant;
};

Ich hab hier jetzt nur das wichtigste kommentiert-für die ganauen Deteils gibts http://www.uni-ulm.de/~s_cwanie/spec_pict/bmp.html.
Hiernach kommen dann die eigentlichen Bilddateien als einzelne Farbwerte (RGB-Farbsystem).
Machen wir uns also eine Klasse für Texturen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
class PH3DTextureBuffer
{
public:
    int AufloesungX;
    int AufloesungY;
    IDirect3DTexture9 *HardBuffer;
    PH3DBitmapColor *SoftBuffer;
    void Laden(char *filename);
    void Erstellen(IDirect3DDevice9 *D3DDev);
    void Darstellen();
};


Der Softbuffer dient uns hierbei als zwischenspeicher-in ihn laden wir die Texturdaten mit der "Laden"-Funktion und schreiben dann die Daten mit der "Erstellen"-Funktion in den TexturenBuffer.
Der SoftBuffer Besteht dabei aus Objekten dieser Struktur:

C-/C++-Quelltext

1
2
3
4
5
6
7
struct PH3DBitmapColor
{
    unsigned char Blue;
    unsigned char Green;
    unsigned char Red;
    unsigned char Alpha;
};

Zum Laden der Textur bedienen wir uns dieser Funktion:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void PH3DTextureBuffer::Laden(char *filename)
{
    ifstream ifs(filename, ios::binary);
    PH3DBitmapHeader Header;
    PH3DBitmapInfo Info;
    ifs.read((char*)&Header, 14);
    ifs.read((char*)&Info, 40);
    AufloesungX=Info.biWidth;
    AufloesungY=Info.biHeight;
    SoftBuffer=new PH3DBitmapColor[AufloesungX*AufloesungY];
    for(int i=0; i<AufloesungX*AufloesungY; i++)
    {
        ifs.read((char*)&SoftBuffer[i], 3);
        SoftBuffer[i].Alpha=(SoftBuffer[i].Red+SoftBuffer[i].Blue+SoftBuffer[i].Green)/3;
    }
        ifs.close();
}

Sie funktioniert wie folgt: Erst laden wir den Header und den Infoheader mit der ifstream::read-Methode. Aus dem Infoheader erhalten wir die Maße des Bildes. Dann Erstellen wir den SoftBuffer in der benötigten Größe(für jeden Pixel ein PH3DBitmapColor). Dann kommt dasd eigentliche Herz der Funktion. Wir laden jeweils von jedem Pixel die RGB-Werte ein und Setzen den Alphawert auf den Durchschnitt der anderen Farben(man kann hier natürlich auch noch Colorkeys u.s.w. einbauen). Jetzt haben wir die gesamte Textur in dem Soft Buffer und müssen sie nur noch in die Grafikkarte stopfen. Nichts leichter als das, dafür gibts die nächste Funktion:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
void PH3DTextureBuffer::Erstellen(IDirect3DDevice9 *D3DDev)
{
    PH3DDev.D3DDev->CreateTexture(AufloesungX, AufloesungY, 0, D3DUSAGE_AUTOGENMIPMAP, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
        &HardBuffer, NULL);
    D3DLOCKED_RECT Rect; 
    HardBuffer->LockRect(0, &Rect, NULL, 0); 
    memcpy(Rect.pBits, (void*)SoftBuffer, (AufloesungX*AufloesungY*4)); 
    HardBuffer->UnlockRect(0);
}

Erst erstellen wir eine Textur in der benötigten Größe. Dann sperren wir sie und Kopieren den gesamten SoftBuffer in das erhaltene gesperrte Rechteck(D3DLOCKED_RECT).
Dir entsperren die Textur und schon haben wir die Textur von der Datei in die Grafikkarte geladen. Fertig!
Als kleinen Ausklang:

C-/C++-Quelltext

1
2
3
4
void PH3DTextureBuffer::Darstellen()
{
    PH3DDev.D3DDev->SetTexture(0, HardBuffer);
}

Damit setzen wir die textur(das habt ihr euch nicht gedacht, oder :lol: ).

big_muff

Alter Hase

Beiträge: 460

Wohnort: Schweiz

Beruf: Informatikstudent (4. Semester)

  • Private Nachricht senden

2

02.08.2006, 20:56

Was mich mal interessieren würde, ist wie man JPG's ohne D3DX liest. Das ist eigentlich der einzige Grund, warum ich das noch verwende...
Nur Idioten halten Ordnung, ein Genie beherrscht das Chaos.[size=7]

[/size]HardFate - Ein Start, Ein Ziel, Viele Wege[size=7]

[/size]Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.

Phili

unregistriert

3

02.08.2006, 20:59

@big_muff
Dafür brauste irgendeine Spezial-lib.

4

02.08.2006, 21:00

nimm lieber tga ... guck dir einfach nehes loader dazu an und schreibs um :)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

Phili

unregistriert

5

02.08.2006, 21:01

@Devil
Meinst du mich? Also ich bin mit bmp bisher ganz gut bedient-aber Alphakanal ist natürlich schon was tollen... :D [/url]

DarkFitzi

Alter Hase

Beiträge: 608

Wohnort: Eisenberg, Thüringen

Beruf: Schüler, 10te Klasse

  • Private Nachricht senden

6

02.08.2006, 21:55

mit nehe meint er dieses Tutorial, beziehungsweise den der es geschrieben hat.
Ich würde die Welt gern verbessern, doch Gott gibt mir den Sourcecode nicht! :-(

7

02.08.2006, 22:37

Zitat von »"Phili"«

aber Alphakanal ist natürlich schon was tollen... :D

ja, und verlustfreie kompression

Phili

unregistriert

8

03.08.2006, 11:27

@WarMuuh
Naja, mein Tutorial ist über bmps-wenn man mal weiß wies mit denen geht, wird mans wohl auch mit tgas schaffen...

Anonymous

unregistriert

9

03.08.2006, 18:45

Also wenn Du schon Routine darin bekommst, dann solltest Du auch die Sicherheit beachten!

Wenn die Datei nicht existiert, knallt deine Funktion weg. Dazu ist die STL genau im Bereich von Binärdaten ein absoluter Gefahrenfaktor! Daher sollte man genau hier mit ReadFile arbeiten, da man nur da Testen kann, ob die Daten beschädigt sind, infiziert sind, oder ob das Lesen schief gegangen ist.

Auch das Locken mußt Du testen. Das sind alles enorme Gefahrenstellen!

Und beschreib nächstes mal mehr die Funktionen die Du benutzt, was die machen, wofür die Parameter sind usw. Denn genau wie in Deinem ShaderTutorial gehst Du auf den Kernbestand sogut wie, oder gar nicht richtig ein. D3DX springt doch genau in diesem Fall ein, also wenn man schon gegen D3DX schreibt, dann sollte man auch die Funktionen, die eben mehr bringen auch gut beschreiben ;)

Phili

unregistriert

10

03.08.2006, 22:49

@nix da

Auf das mit der Sicherheit hab ich jetzt nciht mehr extra hingewiesen, aber ich hab alle meine Tutorials so konzipiert, dann man sie zum verstehen liest und dann en eigene Version davon schreibt. Das das so wies ist ziemlicher Selbstmord wäre ist mir bewusst ;) .
Aber es ist ja nciht so, das man beio stl nicht abchecken könnte, obs nen fehler gab. Dafür ist doch

C-/C++-Quelltext

1
ifstream::failed() 
da :) . Ich hab sowas aber jetzt nciht in den Code geschrieben, weil ich viel denk, dasser einfacher zu verstehen ist, wenn er kurz und übersichtlich ist.

Werbeanzeige