Transparenz - Direct3D - 2D
-
Hi!
Ich hab jetzt schon lang gesucht und auch schon in ein paar threads danach gefragt aber ich finde leider nichts was mir weiterhilft:
Ich bastle gerade ein 2D-Spiel und würde gerne bestimmte Bilder transparent machen aber eben nicht eine bestimmte Farbe des Bildes sondern das ganze Bild halbdurchsichtig machen. (oder zu einem bestimmten Prozentsatz, den ich einstellen kann wenn das möglich ist)
Ich hab zwar ein schlaues Buch in dem steht dass das mittels Alphablendings möglich ist allerdings steht nicht drin WIE...
Leider verstehe ich nichts von alphablending; bislang hab ich nur eine Farbe beim Laden des Bildes angegeben die dann 100% transparent wird.
Kennt ihr da ein Tutorial oder Beispielcode?Bin für jede Hilfe dankbar!
MfG Kuldren
-
Beispielcode:
http://turing.fh-landshut.de/~jamann/SpaceFighter beta 0.7.zipTutorial das erklärt was Alpha Blending ist:
http://turing.fh-landshut.de/~jamann/Alphablending.htmlTutorial zur 2D Programmierung mit D3D:
http://turing.fh-landshut.de/~jamann/dg1html/vertexwahn.htm
http://turing.fh-landshut.de/~jamann/dfwds.html
-
Erstmal danke für die Links!
http://turing.fh-landshut.de/~jamann/dg1html/vertexwahn.htm:
Bei DirectDraw verwendete man für Transparents einen ColorKey. Das Prinzip dahinter war eigentlich ganz einfach: Es wurden alle Pixel mit einer bestimmten Farbe nicht auf den Bildschirm gerendert. In D3D gibt es keinen Colorkey, dafür aber das Alphablending. Mit Alphablending kann man Objekte auch halbdurchscheinend darstellen. Um aber auf das Ergebnis eines Colorkeys zu kommen, werden wir ähnlich wie beim Colorkey einen Farbwert als Transparente Farbe definieren und mit Hilfe von Alphablending Transparents erzeugen.
->Um eine einzige Farbe 100% durchsichtig erscheinen zu lassen verwende ich
D3DCOLOR_XRGB(255,0,255)beim aufruf aber ich möchte (wie in dem Text erwähnt) eine halbdurchsichtige Textur darstellen um z.B. den Fog of War oder ein Schutzschild darzustellen.
Zu dem kompletten durchsichtig- machen findet sích viel aber leider nicht zu dem 50% transparent machen.
-
struct SVertex { tbVector3 Position; D3DCOLOR Col; tbVector2 Tex; }; const DWORD FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2; ... D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); Vertices[0].Col = D3DCOLOR_ARGB(127, 255, 255, 255); ...Bei der Farbe stellst du den Alphawert ein.
-
struct SVertex { tbVector3 Position; D3DCOLOR Col; tbVector2 Tex; }; const DWORD FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2; ... D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); Vertices[0].Col = D3DCOLOR_ARGB(127, 255, 255, 255); ...->Ich hab versucht das in den Code(eigentlich der Code von einem der Beispiele die Vertexwahn gepostet hat) einzubauen aber ich weiß leider nicht wie ich den Teil mit dem Vertices[0].Col einbauen soll?!...weil die Farbe ja nirgends abgefragt bzw übergeben wird; genauso wie das const DWORD FVF..
Ich hab auch versucht einfach beim Aufruf von CreateTextureFromFileExA(...)
den D3DCOLOR_ARGB(127,255,0,255)-Wert einzubauen aber es hat genau die gleiche Funktion wie D3DCOLOR_XRGB(255,0,255) selbst wenn ich vorher den ENABLE BLOCK aufrufe:D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);habt ihr vlt einen funktionierenden Code für CreateTextureFromFileExA mit den ganzen Initialisierungen und ENABLES.
-
Ok, ich versuche es mal etwas ausführlicher

struct SVertex { D3DVECTOR Position; D3DCOLOR Col; D3DVECTOR Tex; }; const DWORD FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2;Das ist die Struktur für einen Vertex. Du hast wahrscheinlich ohne Farbe gearbeitet, aber die können wir benutzen, um den Alphakanal zu nutzen.
Vor dem rendern oder beim Initialisieren musst du dann noch diese Einstellungen vornehmen:
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); D3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); D3DDevice->SetFVF(FVF);Mit den Texture Stage States benutzt man das Multi-Texturing in Direct3D. Dazu wird man sicherlich jede Menge in der Hilfe finden. Wichtig zu wissen ist, dass Farbwerte von mehreren Texturen miteinander kombiniert werden. Daher können auch Alphawerte kombiniert werden. In diesem Fall sagen wir DirectX mit SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE) dass das erste Argument den Alphawert aus der Textur nehmen soll. SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE) nimmt den Alphawert aus der Farbe, die wir zu jedem Vertex dazu speichern.
SVertex Vertices[4]; D3DDevice->SetTexture(0, DeineTextur); Vertices[0].Position = ...; Vertices[1].Position = ...; Vertices[2].Position = ...; Vertices[3].Position = ...; for (int j = 0; j < 4; j++) { Vertices[j].Col = D3DCOLOR_ARGB(127, 255, 255, 255); Vertices[j].Tex = ...; } D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Vertices, sizeof(SVertex));So kannst du das ganze dann rendern. Durch D3DCOLOR_ARGB(127, 255, 255, 255) wird die Textur dann halbdurchsichtig..
[Edit]
Ach ja, die Textur lädst du einfach ohne Color-Keying.
-
Ich weiß die Fragen nerven aber ich kenne mich mit Vertices und Co leider noch nicht so gut aus..........
Ich hab jetzt den Code in meine Direct3D Klasse eingebaut um zu testen ob es funktioniert allerdings wird das Bild nicht angezeigt.
Bisher habe ich Bilder mit meiner Sprite Klasse geladen und dargestellt:void CSprite::Create(LPDIRECT3DDEVICE9 lpDevice, LPCSTR lpFileName ) { m_lpDevice = lpDevice; // Sprite anlegen D3DXCreateSprite(m_lpDevice,&m_lpSprite); // Inforationen über die Textur holen D3DXIMAGE_INFO ImgInfo; D3DXGetImageInfoFromFile(lpFileName,&ImgInfo); // Textur anlegen D3DXCreateTextureFromFileEx(m_lpDevice, lpFileName, ImgInfo.Width, ImgInfo.Height, 1,0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, RGB(255,0,255),0,0, &m_lpTexture); // Breite und Höhe speichern m_Width = ImgInfo.Width; m_Height = ImgInfo.Height; m_vRotationCenter = D3DXVECTOR2((float)m_Width/2,(float)m_Height/2); // Skalierung und Schrittweite setzen m_vScale = D3DXVECTOR2(1.0f,1.0f); // Schrittweite des Sprites bei Bewegung m_StepX = 10.0f; m_StepY = 10.0f; }Darstellen:
void CSprite::Draw(const RECT *source) { m_Rotation=0; m_lpSprite->Draw(m_lpTexture, source, &m_vScale, &m_vRotationCenter, m_Rotation, &m_vPosition, 0xFFFFFFFF); }Jetzt habe ich das ganze direkt in meine Direct3D Klasse eingebaut:
Außerhalb der CDirect3D-Klasse in Direct3D.h definiert:
struct SVertex { D3DVECTOR Position; D3DCOLOR Col; D3DVECTOR Tex; }; const DWORD FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2;und in der CDirect3D.init hab ich den Block eingefügt
m_lpD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); m_lpD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); m_lpD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); m_lpD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); m_lpD3DDevice->SetFVF(FVF);void CDirect3D::drawtexture(){ char lpFileName[512]; sprintf(lpFileName,"C:/TANK1.BMP"); D3DXGetImageInfoFromFile(lpFileName,&ImgInfo); D3DXCreateTextureFromFileEx(m_lpD3DDevice, lpFileName, ImgInfo.Width, ImgInfo.Height, 1,0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0,0,0, &m_lpTexture); SVertex Vertices[4]; m_lpD3DDevice->SetTexture(0, m_lpTexture); Vertices[0].Position.x = 50; Vertices[0].Position.y = 50; Vertices[1].Position.x = 50; Vertices[1].Position.y = 50+ImgInfo.Height; Vertices[2].Position.x = 50+ImgInfo.Width; Vertices[2].Position.y = 50+ImgInfo.Height; Vertices[3].Position.x = 50+ImgInfo.Width; Vertices[3].Position.y = 50; for (int j = 0; j < 4; j++) { Vertices[j].Col = D3DCOLOR_ARGB(127, 255, 255, 255); // Vertices[j].Tex = ...; ###-> ??? } m_lpD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Vertices, sizeof(SVertex)); }Dabei weiß ich leider nicht was es mit dem "Vertices[j].Tex=...;" auf sich hat...
Die Koordinaten der Vertices hab ich nach der Annahme eingebaut:------------------------------------------------- 1------4 1=Vertices[0] | | 2=Vertices[1] | | 3=Vertices[2] | | 4=Vertices[3] 2------3 -------------------------------------------------Wird das nicht sehr aufwändig für jedes Sprite das ich darstellen will alle 4 Punkte beim Bewegen neuzuberechnen...(also ich meine Codeaufwändig...bis jetzt war das mit mit meiner Spriteklasse ziemlich einfach)
+Dann muss ich doch für jedes Bildm_lpD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Vertices, sizeof(SVertex));einbauen oder?
-
Hmm, ich kenne mich zwar mit Sprites überhaupt nicht aus, aber ich habe in der DirectX-Dokumentation das hier als Beschreibung für den letzen Paramter der Draw-Methode gefunden:
Color
[in] D3DCOLOR type. The color and alpha channels are modulated by this value. A value of 0xFFFFFFFF maintains the original source color and alpha data. Use the D3DCOLOR_RGBA macro to help generate this color.Also, versuche einfach mal das hier:
void CSprite::Draw(const RECT *source) { m_Rotation=0; m_lpSprite->Draw(m_lpTexture, source, &m_vScale, &m_vRotationCenter, m_Rotation, &m_vPosition, 0x80FFFFFF); }0x80FFFFFF steht für einen Alphawert von 128 und rgb jeweils 255.
Anstelle von
0x80FFFFFFkannst du auch
D3DCOLOR_ARGB(128, 255, 255, 255)benutzen.
Meinen Code lässt du einfach weg, der lässt sich zusammen mit Sprites (soweit ich sehe) nicht benutzen.
Color-Keying beim Laden der Textur benötigst du aber nur, wenn du eine bestimmte Farbe komplett aus dem Bild nehmen willst.
-
Ja damit funktionierts! Danke!....
Hätt ich echt selber draufkommen können *grml*