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
D3DXSaveSurfaceToFilezum 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
IDirect3DTexture9undID3DXSpritegelesen - 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 mitStretchRectzusammensetzen 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
StretchRectum die Layer zu generieren, da ja die Alpha-Werte übernommen werden. In meiner Schleife zum Erstellen der Layer generiere ich einIDirect3DTexture9Objekt pro Layer. PerGetSurfaceLevelhabe ich Zugriff auf das Surface welche zu der Texture gehört und kann es gewohnt mitStretchRectbefüllen. Beim Rendern nutze ich jedochID3DXSpritewelches 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
