To jest moje pierwsze pytanie na temat StackOverflow, hurra! Mogę szczerze powiedzieć, że używam StackOverflow na co dzień zarówno dla mojej pracy, jak i osobistych tajemnic programistycznych. 99,9% czasu, w którym rzeczywiście znajduję odpowiedź, której potrzebuję, również tutaj, co jest świetne!SlimDX/DirectX9/C# - Jak uzyskać dostęp do danych pikseli w tekstury
Mój obecny problem faktycznie mnie trochę zaskoczył, ponieważ nie mogę znaleźć niczego, co faktycznie działa. Przeczytałem już kilka postów na GameDev.net i znalazłem inne zasoby w sieci, ale nie mogę tego rozwiązać.
Jestem w trakcie przenoszenia małego silnika 2D, który napisałem dla XNA do SlimDX (tylko DirectX9 w tej chwili), co było dobrym posunięciem, ponieważ dowiedziałem się więcej o wewnętrznych działaniach DirectX w ciągu zaledwie kilku dni niż w ciągu sześciu miesięcy pracy z XNA. Większość moich podstawowych funkcji renderowania została wykonana i faktycznie udało mi się odtworzyć XNA SpriteBatch z mnóstwem dodatkowych funkcji (których tak naprawdę brakowało mi w XNA).
Jedną z ostatnich rzeczy, do których próbuję dostać się do pracy, jest wyodrębnienie prostokąta źródłowego z zadanej tekstury i użycie go do kafelkowania. Dlaczego: Kiedy nie układasz kafelków, możesz po prostu zadzierać promieniowaniem UV, aby uzyskać źródło, które chcesz wyświetlić (np. 0,3; 0,3 do 0,5; 0,5), ale kiedy układasz kafelek, potrzebujesz UV do płytek (0; 0 do 2; 2) oznacza dwa razy obrazy płytek) i dlatego potrzebna jest tekstura wycięcia.
Aby długie opowiadanie, staram się korzystać z następujących powodów:
DataRectangle dataRectangle = sprite.Texture.LockRectangle(0, LockFlags.None);
Format format = sprite.Texture.GetLevelDescription(0).Format;
byte[] buffer = new byte[4];
dataRectangle.Data.Read(buffer, ([y] * dataRectangle.Pitch) + ([x] * 4), buffer.Length);
texture.UnlockRectangle(0);
Próbowałem różnych pikseli, ale wszystkie wydają się dawać fałszywe dane. Na przykład, próbowałem użyć mojego obecnego awatara, aby sprawdzić, czy bufor, który dostałem z DataRectangle, pasuje do rzeczywistego piksela na obrazku, ale bez powodzenia (nawet sprawdzony, czy Format jest poprawny, jaki to jest).
Co robię źle? Czy istnieje lepszy sposób na zrobienie tego? A może moja historia UV jest błędna i czy można ją rozwiązać znacznie łatwiej niż wycinanie prostokąta źródłowego przed jej układaniem?
Dziękuję za poświęcony czas,
Lennard Fonteijn
Aktualizacja # 1
I rzeczywiście udało się wyeksportować dane pikseli na bitmapę stosując następującą konwersję z tablicy bajtów:
int pixel = (buffer[0] & 0xFF) | ((buffer[1] & 0xFF) << 8) | ((buffer[2] & 0xFF) << 16) | ((255 - buffer[3] & 0xFF) << 24);
Dane nie wydają się tak nieprawdziwe, jak myślałem. Moim następnym problemem jest jednak chwytanie pikseli określonych w prostokącie źródłowym i kopiowanie ich do nowej tekstury. Obraz, który próbuję wyciąć, ma wymiary 150 x 150, ale z jakiegoś powodu jest rozciągnięty do obrazu 256 x 256 (moc dwóch), ale kiedy faktycznie próbuje uzyskać dostęp do pikseli powyżej 150x150, generuje wyjątek OutOfBounds. Ponadto, gdy próbuję stworzyć drugą pustą teksturę o rozmiarze 256x256, bez względu na to, co w nią włożę, okazuje się ona całkowicie czarna.
Oto mój bieżący kod:
//Texture texture = 150x150
DataRectangle dataRectangle = texture.LockRectangle(0, LockFlags.None);
SurfaceDescription surface = texture.GetLevelDescription(0);
Texture texture2 = new Texture(_graphicsDevice, surface.Width, surface.Height, 0, surface.Usage, surface.Format, surface.Pool);
DataRectangle dataRectangle2 = texture2.LockRectangle(0, LockFlags.None);
for (int k = sourceX; k < sourceHeight; k++)
{
for (int l = sourceY; l < sourceWidth; l++)
{
byte[] buffer = new byte[4];
dataRectangle.Data.Seek((k * dataRectangle.Pitch) + (l* 4), SeekOrigin.Begin);
dataRectangle.Data.Read(buffer, 0, 4);
dataRectangle2.Data.Seek(((k - sourceY) * dataRectangle2.Pitch) + ((l - sourceX) * 4), SeekOrigin.Begin);
dataRectangle2.Data.Write(buffer, 0, 4);
}
}
sprite.Texture.UnlockRectangle(0);
texture2.UnlockRectangle(0);
_graphicsDevice.SetTexture(0, texture2);
Więc moje nowe (dodatkowe) pytania: Jak mogę przenieść nad pikseli z jednego do innego mniejszego tekstury tekstury, w tym kanałem Alpha? Dowolne dlaczego raport SurfaceDescription daje 256x256, gdy moja oryginalna tekstura ma wymiary 150 x 150?
Myślę, że powinien on zostać opublikowany pod adresem http://gamedev.stackexchange.com. Każdy moderator powinien mieć możliwość przeniesienia go tam, jeśli to prawda. –
To dobre pytanie - i na temat tutaj ... ale tak, możesz uzyskać dodatkową pomoc. – jcoder
Zaktualizowałem pytanie, podając nowe informacje. –