[DirectX c++] Alpha Blending png

Hallo

Ich hab hier schon mal so was ähnliches gefragt, seit dem weiss ich auch, was alles nicht geht ;)
hab mich dann in letzter Zeit mit anderem beschäftigt und stosse jetzt wieder auf dasselbe sch**** Problem.

Ich möcht eigentlich "einfach" nur die Transparenz eines PNG Bildes verwenden.
Mit Surfaces und StretchRect() scheint das nicht zu funktioniren.

Wäre das mit Texturen möglich?
Leider hab ich noch fast nichts mit Texturen gemacht, wie könnte ich ein PNG in eine Texture laden und dann unter berücksichtigung der Alpha Werte in den Backbuffer kopieren?

Ach ja ich hab ein Beispiel mit dx8 und ddraw (Color-keying), möchte es aber modern machen (Direct-Graphics) :D

Danke im Voraus für jede Hilfe!
 
DirectDraw scheidet da praktisch aus, da es mit Alpha nichts am Hut hat (Colorkeys ja, aber das ist ja nur Pixel da oder Pixel weg).

Mit DirectGraphics (bzw. Direct3d) geht das: Es gibt eine Funktion in der D3DX-Helper-Library namens D3DXCreateTextureFromFile. Da kannst du schön die Colorkeys angeben und das Alpha wird auch mit in die Textur übernommen. Um einfach mit Texturen zu arbeiten gibt es schöne Samples schon im DirectX SDK, ansonsten wirst du auch im Web bestimmt fündig!
 
Ok werde es so machen.

Wie kopiere ich jetzt diese Textur in den Backbuffer?
Ist das nur über einen Sprite möglich?

edit:
Ach nein :(
Hab gerade bemerkt, dass ich auch nicht quadratische Flächen brauche.
Texturen kann ich also nicht verwenden.
 
Zuletzt bearbeitet:
Direct 3D Funktioniert anders wie Direct Draw. Da wird immer in den Backbuffer gezeichnet. Und wenn du Sprites verwenden willst musst du auf transformierte Vertices zurückgreifen. Ist nicht wirklich schwer. Ein Rechteck zeichnen die Textur oder den Auschnitt drauflegen, das wars. Das Flexible Vertex Format muss noch geändert werden, dass das RHW element Vorhanden ist.
 
Habs jetzt mal probiert. Bei diesem Code sehe ich aber nur einen schwarzen Bildschrim.
Ich arbeite das erste mal mit Vertices und Texturen und denke dass ihr den oder die Fehler recht schnell finden werdet.
(In etwa so war das doch gemient, oder?)

Schon mal Danke im Voraus für die, die sich Zeit nehmen!!

EDIT: Dies ist der aktuelle Code (nicht der, bei dem die oben beschriebenen Fehler auftraten.

Code:
//______________________________________________________TileMap.cpp_____________________________________________________________ 

// I N C L U D E S /////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef TILEMAP_H
#define TILEMAP_H
#include "TileMap.h"
#endif

#include "iostream.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>

// G L O B A L S ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define BUFFERSIZE 1024

#define TILE_HEIGHT 64
#define TILE_WIDTH 128
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)

int x_Scroll = 0;
int y_Scroll = 0;

const int  NUMBER_OF_VERTICES = (SCR_WIDTH/TILE_WIDTH)*(SCR_HEIGHT/TILE_HEIGHT)*2*3*2;


LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; // Buffer to hold vertices

struct CUSTOMVERTEX
{
    float x, y, z, rhw; // The transformed position for the vertex
    DWORD color;        // The vertex color
	float tu, tv;
};

// Vertices für die Tile Texturen
CUSTOMVERTEX vertices[NUMBER_OF_VERTICES];

// F U N C T I O N S //////////////////////////////////////////////////////////////////////////////////////////////////////////

// KONSTRUKTOR ================================================================================================================
CTileMap::CTileMap()
{
//int ***Array, **Array0, *Array00;
  pDatei = NULL;
  pDatei = fopen("..\\maps\\map.txt","r");
	
	char Buffer[BUFFERSIZE];

	if(NULL == pDatei)
	{
		// Fehler, Programm beenden
		return;
	}
	
	// Die grösse des Vectors anpassen
	fgets(Buffer,BUFFERSIZE-1,pDatei);
	sscanf(Buffer,"%i",&m_MapHeight);
	
	fgets(Buffer,BUFFERSIZE-1,pDatei);
	sscanf(Buffer,"%i",&m_MapWidth);

	fgets(Buffer,BUFFERSIZE-1,pDatei);
	sscanf(Buffer,"%d",&m_NumberOfTiles);
	VecTileSurface.resize(m_NumberOfTiles);
	
	TileMap.resize(m_MapHeight);

	for(int i=0; i< m_MapHeight; i++)
		TileMap[i].resize(m_MapWidth);
	
	char* Token;
	Token = new char[BUFFERSIZE];
	char* Token1;
	Token1 = new char[BUFFERSIZE];

	for(int j=0; j<m_MapHeight; j++)
	{
		fgets(Buffer,BUFFERSIZE-1,pDatei);
		for(int i=0; i<m_MapWidth; i++)
		{
			//Damit nicht immer das gleiche gelesen wird
			if(i==0)
			{
				Token = strtok(Buffer," ");
			}
			else
			{
				Token = strtok(NULL," ");
			}

			sscanf(Token,"%d",&TileMap[j][i]);
		}
	}


} // KONSTRUKTOR	
 
// DESTRUKTOR =================================================================================================================

CTileMap::~CTileMap()
{
	// Momentan keine aufgaben für Destruktor
} // DESTRUKTOR


// INIT ======================================================================================================================

CTileMap::Init(LPDIRECT3DDEVICE9 Device)
{
	m_lpD3DDevice = Device;
	char Buffer[BUFFERSIZE];
	char *tmp = NULL;
	

	//Backbuffer holen
	m_lpD3DDevice->GetBackBuffer(0,0,
                                 D3DBACKBUFFER_TYPE_MONO,
                                 &m_lpBackBuffer);

	// Oberflächen in denen die Tiles gespeichert sind erstellen
	for(int i=0; i<m_NumberOfTiles; i++)
	{
		//HRESULT ErrorTest;
		fgets(Buffer,BUFFERSIZE-1,pDatei);
		Buffer[BUFFERSIZE-1] = 0;
		tmp = Buffer;

		while(*tmp>=0x20) 
		{
			tmp++;
		}

		*tmp=0;

		D3DXIMAGE_INFO ImageInfo;

		D3DXGetImageInfoFromFile(Buffer,&ImageInfo);

		if(FAILED( D3DXCreateTextureFromFileEx(   
												m_lpD3DDevice,
												Buffer,
												TILE_WIDTH,
												TILE_HEIGHT,
												1,
												0,
												D3DFMT_A8R8G8B8,
												D3DPOOL_MANAGED,
												D3DX_FILTER_NONE,
												D3DX_FILTER_NONE,
												0, // Color Key
												&ImageInfo,
												0,
												&VecTileSurface[i]
											    )))
		{
			MessageBox(NULL,"Textur nicht gefunden!","TEXTURFEHLER", MB_OK);
		}

	}
	tmp = NULL;

	fclose(pDatei);

	// Vertexbuffer erstellen
	m_lpD3DDevice->CreateVertexBuffer( NUMBER_OF_VERTICES*sizeof(CUSTOMVERTEX),
									   0, D3DFVF_CUSTOMVERTEX,
                                       D3DPOOL_DEFAULT, &g_pVB, NULL);

	VOID* pVertices;
    g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 );
    memcpy( pVertices, vertices, sizeof(vertices) );
    g_pVB->Unlock();
	
	m_lpD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	//m_lpD3DDevice->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_BLENDDIFFUSEALPHA);
	
	m_lpD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
	m_lpD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
	m_lpD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); 



	
} // INIT

// DRAW ======================================================================================================================

CTileMap::Draw(void)
{
	// Tiles Zeichnen
	int j, i;
	int x = 0, y = 0;
	int x_offset = TILE_WIDTH/2;
	int y_offset = TILE_HEIGHT/2;
	int VertexIndex = 0;

	for(j=0; j<m_MapHeight; j++)
	{
		// Aktuelles Tile ist oberhalb des sichtbaren Bereichs
		if(y-y_Scroll < 0)
		{
			y += y_offset;
			continue;
		}

		// Aktuelles Tile ist unterhalb des sichtbaren Bereichs
		if(y-y_Scroll > SCR_HEIGHT-TILE_HEIGHT)
			break;

		for(i=0; i<m_MapWidth; i++)
		{
			// Aktuelles Tile zu weit links
			if(x-x_Scroll < 0)
			{
				x += TILE_WIDTH;
				continue;
			}
			// Aktuelles Tile zu weit rechts
			else if(x-x_Scroll > SCR_WIDTH-TILE_WIDTH)
				break;
			else
			{
					// Vertices für Texturen
					
				
					// Oben rechts
					vertices[VertexIndex].color = 0x00000000;
					vertices[VertexIndex].x		= float(x-x_Scroll+TILE_WIDTH);
					vertices[VertexIndex].y		= float(y-y_Scroll);
					vertices[VertexIndex].z		= 0.5f;
					vertices[VertexIndex].tu	= 1.0f;
					vertices[VertexIndex].tv	= 0.0f;

					VertexIndex++;
					// Unten links
					vertices[VertexIndex].color = 0x00000000;
					vertices[VertexIndex].x		= float(x-x_Scroll);
					vertices[VertexIndex].y		= float(y-y_Scroll+TILE_HEIGHT);
					vertices[VertexIndex].z		= 0.5f;
					vertices[VertexIndex].rhw	= 1.0f;
					vertices[VertexIndex].tu	= 0.0f;
					vertices[VertexIndex].tv	= 1.0f;
					// Oben links
					VertexIndex++;
					vertices[VertexIndex].color = 0x00000000;
					vertices[VertexIndex].x		= float(x-x_Scroll);
					vertices[VertexIndex].y		= float(y-y_Scroll);
					vertices[VertexIndex].z		= 0.5f;
					vertices[VertexIndex].rhw	= 1.0f;
					vertices[VertexIndex].tu	= 0.0f;
					vertices[VertexIndex].tv	= 0.0f;


					VertexIndex++;
					
					// Oben rechts
					vertices[VertexIndex].color = 0x00000000;
					vertices[VertexIndex].x		= float(x-x_Scroll+TILE_WIDTH);
					vertices[VertexIndex].y		= float(y-y_Scroll);
					vertices[VertexIndex].z		= 0.5f;
					vertices[VertexIndex].rhw	= 1.0f;
					vertices[VertexIndex].tu	= 1.0f;
					vertices[VertexIndex].tv	= 0.0f;

					VertexIndex++;
					// Unten rechts
					vertices[VertexIndex].color = 0x00000000;
					vertices[VertexIndex].x		= float(x-x_Scroll+TILE_WIDTH);
					vertices[VertexIndex].y		= float(y-y_Scroll+TILE_HEIGHT);
					vertices[VertexIndex].z		= 0.5f;
					vertices[VertexIndex].rhw	= 1.0f;
					vertices[VertexIndex].tu	= 1.0f;
					vertices[VertexIndex].tv	= 1.0f;

				    VertexIndex++;
					// Unten links
					vertices[VertexIndex].color = 0x00000000;
					vertices[VertexIndex].x		= float(x-x_Scroll);
					vertices[VertexIndex].y		= float(y-y_Scroll+TILE_HEIGHT);
					vertices[VertexIndex].z		= 0.5f;
					vertices[VertexIndex].rhw	= 1.0f;
					vertices[VertexIndex].tu	= 0.0f;
					vertices[VertexIndex].tv	= 1.0f;
	

					VertexIndex++;

				x += TILE_WIDTH;
				

			}
		}
		if(j&1)	// Ungerade Zeile (Nächste Zeile gerade!)
			x = 0;
		else
			x = x_offset;
		
		y += y_offset;
	}	
	
	VOID* pVertices;
	g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 );
	memcpy( pVertices, vertices, sizeof(vertices) );
	g_pVB->Unlock();

	m_lpD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
	m_lpD3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX);

	//m_lpD3DDevice->SetTexture(0,VecTileSurface[0]);
	//m_lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0,NUMBER_OF_VERTICES/3);

	int StartVertex = SCR_WIDTH/TILE_WIDTH*SCR_HEIGHT/TILE_HEIGHT*3*4-6;
//	char testtext;
	j-=y_Scroll/TILE_HEIGHT;
	i-=x_Scroll/TILE_WIDTH;
	
	int tempi = i;
	while(j>=0)
	{
		tempi = i;
		while(tempi>=0)
		{
			//MessageBox(NULL,"Test","Test",MB_OK);


			m_lpD3DDevice->SetTexture(0,VecTileSurface[TileMap[j][tempi]]);
			m_lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST,StartVertex,2);
			if(StartVertex >= 6)
			StartVertex -= 6;

		//sprintf (&testtext,"%d",StartVertex);
		//MessageBox(NULL,&testtext,"Test",MB_OK);
			tempi--;
		}			

		j--;			
		
	}

} // DRAW


//______________________________________________________TileMap.cpp____________________________________________________________
 
Zuletzt bearbeitet:
Du machst ein paar Fehler. Wenn du zeichnest musst du vorher den Backbuffer Löschen, dann BeginnScene und wenn du Fertig bist EndScene und Present aufrufen. Wenn du nur ein Rechteck Zeichnen willst brauchst du dafür nicht direkt einen VertexBuffer anzulegen.

Code:
 	//Backbuffer holen
	m_lpD3DDevice->GetBackBuffer(0,0,
                                 D3DBACKBUFFER_TYPE_MONO,
                                 &m_lpBackBuffer);

waurm eigentlich das?

Den Backbuffer braucht man sich nicht holen. Der wird von Direct3D erstellt und es wird automatisch in den Backbuffer gezeichnet
 
BeginScene und EndScene werden in der Main Funktion aufgerufen.
Wenn ich Present aufrufe, flimmert der Bildschirm extrem .(schwarz und weiss)
Den Backbuffer hole ich, weil ich noch mit Surfaces arbeiten werde.

So sieht der entsprechende Teil Main Funktion aus:
Code:
    while(msg.message != WM_QUIT)
    {
        if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
                                                (Direct3D.GetDevice())->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1, 0);
			Direct3D.BeginScene();
         
			TileMap.Draw();



			Direct3D.EndScene();			
			
			// Present the backbuffer contents to the display
			(Direct3D.GetDevice())->Present( NULL, NULL, NULL, NULL );
        }
    }
 
Begin- und EndScene werden auch über das Direct3DDevice aufgerufen. (nicht nur Clear und Present)
 
Hab bemerkt, dass es nur bei Fullscreen flimmert.
Bei Windowed werden irgendwelche Farben aus dem Hintergrundfenster dargestellt.

EDIT:
Der Backbuffer wurde vor dem Zeichnen nicht richtig gelöscht.(Wie du es ja vermutet hattest)
Jetzt flimmert es nicht mehr, leider wird von der Draw Methode gar nichts gezeichnet.
 
Zuletzt bearbeitet:
*freu-und-singend-und-tanzend-in-die-luft-spring* :)
Jetzt hat s endlich geklappt.
Ich hatte D3DFVF_XYZ definiert, gab die Koordinaten aber im Format D3DFVF_XYZRHW an.
Daran sass ich jetzt den ganzen Tag.

Vielen dank allen, die mir geholfen haben, besonders Flegmon
 
Zuletzt bearbeitet:
Zurück