Probleme mit Transparenz bei DirectX und StretchRect
-
Folgende Situation: ich lade für meine Maps die benötigten Tilesets (mit Magenta als Colorkey, d.h. ich habe keine echt transparenten Pixel im Tileset!) und baue die einzelnen statischen Layer der Map direkt zusammen und cache das als große Surfaces anstatt jeden Frame etliche Tiles einzeln zu rendern. Dies funktioniert ganz grob so:
// === TILESET LOOP === // IDirect3DSurface9 *pTilesetSurface = nullptr; // Create surface HRESULT hResult = Engine::GetInstance()->GraphicsDevice->CreateOffscreenPlainSurface( pTileset->GetImage()->GetWidth(), pTileset->GetImage()->GetHeight(), D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTilesetSurface, nullptr); if(!SUCCEEDED(hResult)) return FALSE; // Load tileset std::wstring strTilesetSource( pTileset->GetImage()->GetSource().begin(), pTileset->GetImage()->GetSource().end()); strTilesetSource = strPathToMap + strTilesetSource; hResult = ::D3DXLoadSurfaceFromFile( pTilesetSurface, nullptr, nullptr, strTilesetSource.c_str(), nullptr, D3DX_FILTER_LINEAR, D3DCOLOR_ARGB(255, 255, 0, 255), nullptr); if(!SUCCEEDED(hResult)) return FALSE; this->m_vTilesets.push_back(pTilesetSurface); /* ... */ // === LAYER LOOP === // IDirect3DSurface9 *pLayerSurface = nullptr; HRESULT hResult = Engine::GetInstance()->GraphicsDevice->CreateOffscreenPlainSurface( pLayer->GetWidth() * 16, pLayer->GetHeight() * 16, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pLayerSurface, nullptr); if(!SUCCEEDED(hResult)) return FALSE; Engine::GetInstance()->GraphicsDevice->ColorFill( pLayerSurface, nullptr, D3DCOLOR_ARGB(0, 0, 0, 0)); for(int x = 0; x < pLayer->GetWidth(); ++x) { for(int y = 0; y < pLayer->GetHeight(); ++y) { const Tmx::MapTile tile = pLayer->GetTile(x, y); if(tile.tilesetId != -1) { int dwTilesetWidth = this->m_pTmxFile->GetTileset(tile.tilesetId)->GetImage()->GetWidth() / 16; std::div_t tileCoords = std::div(tile.id, dwTilesetWidth); RECT srcRect = { tileCoords.rem * 16, tileCoords.quot * 16, tileCoords.rem * 16 + 16, tileCoords.quot * 16 + 16 }; RECT destRect = { x * 16, y * 16, x * 16 + 16, y * 16 + 16 }; Engine::GetInstance()->GraphicsDevice->StretchRect( this->m_vTilesets[tile.tilesetId], &srcRect, pLayerSurface, &destRect, D3DTEXF_NONE); } } }
Versuche ich nun die Layer per
D3DXSaveSurfaceToFile
zum Debuggen zu speichern, dann besitzen sie Alpha-Informationen und lassen sich problemlos übereinanderlegen und liefern das gewünchte Ergebnis. Rendere ich diese nun, funktioniert das aber nicht in meinem Fenster.for(auto iter = this->m_vLayers.begin(); iter != this->m_vLayers.end(); ++iter) { Engine::GetInstance()->GraphicsDevice->StretchRect( *iter, nullptr, Engine::GetInstance()->Backbuffer, nullptr, D3DTEXF_NONE); }
Es entsteht folgende Ausgabe. Überall wo der obere Layer transparent sein sollte ist dieser leider schwarz. Ich würde gerne wissen, ob jemand eine Idee hat, was das Problem ist. Weiterhin habe ich was von
IDirect3DTexture9
undID3DXSprite
gelesen - leider konnte ich das bisher nicht benutzen, auch wenn ich mitbekommen habe, dass Alpha bei Sprites unterstützt wird, da ich nicht herausgefunden habe, wie ich einen Layer mit den Tiles wie oben mitStretchRect
zusammensetzen kann, wenn ich Sprites und Textures nehme anstelle von Surfaces.
-
das problem ist, dass du denkst dass stretchrect rendert, aber
Copy the contents of the source rectangle to the destination rectangle
http://msdn.microsoft.com/en-us/library/windows/desktop/bb174471(v=vs.85).aspx
entsprechend musst du dir einen anderen weg suchen.
btw. schoene pixel art.
-
Danke für den Hinweis - durch Trial and Error habe ich nun eine Möglichkeit gefunden mit dem Problem umzugehen. Meine Tilesets lade ich weiterhin als Surfaces und nutze auch
StretchRect
um die Layer zu generieren, da ja die Alpha-Werte übernommen werden. In meiner Schleife zum Erstellen der Layer generiere ich einIDirect3DTexture9
Objekt pro Layer. PerGetSurfaceLevel
habe ich Zugriff auf das Surface welche zu der Texture gehört und kann es gewohnt mitStretchRect
befüllen. Beim Rendern nutze ich jedochID3DXSprite
welches sich automatisch um die Alpha-Werte kümmert und nun funktioniert alles und ich erhalte ein richtiges Ergebnis!
-
klingt nach einer loesung
vielleicht gleich D3DXLoadTextureFromFile nutzen?ich haette bei der "Art" wohl einfach alles per cpu gemacht und das fertige bild rausgezeichnet, koennte mir vorstellen dass das sogar schneller ist