Wie ändere ich Texturen in SDL mit direktem Pixelzugriff?

8

Ich versuche, SDL_LockTexture und SDL_UnlockTexture zum direkten Bearbeiten von Pixeln in einer Textur zu verwenden. Ich benutze SDL 2.0. Durch Festlegen des Pixelwerts mithilfe des folgenden Codes wird die Textur nicht geändert:

void *pixels;
int pitch;

SDL_LockTexture(mytexture, NULL, &pixels, &pitch);

// Set pixel 100,100 to blue
((uint32_t *)pixels)[100 * 100] = 255;

SDL_UnlockTexture(mytexture);
SDLDude9283
quelle
Was ist der Rückgabewert von SDL_LockTexture (...)?
Jon

Antworten:

2

Das Färben von SDL-Texturen kann etwas schwierig sein. Der folgende Code sollte die wichtigsten Punkte beim Färben einer Textur beschreiben. Der Schlüssel besteht darin, alle erforderlichen Daten aus SDL abzurufen, bevor mit der Änderung der Textur begonnen wird.

Uint32* pixels = nullptr;
int pitch = 0;
int format;

// Get the size of the texture.
int w, h;
SDL_QueryTexture(texture, &format, nullptr, &w, &h);

// Now let's make our "pixels" pointer point to the texture data.
if (SDL_LockTexture(texture, nullptr, (void**)&pixels, &pitch))
{
    // If the locking fails, you might want to handle it somehow. SDL_GetError(); or something here.
}

SDL_PixelFormat pixelFormat;
pixelFormat.format = format;
// Now you want to format the color to a correct format that SDL can use.
// Basically we convert our RGB color to a hex-like BGR color.
Uint32 color = SDL_MapRGB(&pixelFormat, R, G, B);

// Before setting the color, we need to know where we have to place it.
Uint32 pixelPosition = y * (pitch / sizeof(unsigned int)) + x;

// Now we can set the pixel(s) we want.
pixels[pixelPosition] = color;

// Also don't forget to unlock your texture once you're done.
SDL_UnlockTexture(texture);

Jetzt sollten Sie auch beachten, dass das Ändern von Texturen im Code relativ teuer ist. Außerdem ist der Code nicht sehr sauber, da das Bearbeiten von C ++ int-Zeigerarrays und das Übersetzen von Farben in verschiedene Formate zu Problemen führen kann, da die Vorgänge dort möglicherweise nicht so klar sind, wie sie benötigt werden. Dies jedoch nur dann zu tun, wenn dies unbedingt erforderlich ist, sollte nicht zu viele Probleme verursachen.

Möglicherweise möchten Sie auch SDL_SetRenderTargetdie Textur verwenden und ändern, indem Sie sie rendern. Bei einigen Aufgaben ist das Rendern von Grundelementen für die Textur möglicherweise keine Option. Dies ist jedoch der Fall, wenn Sie die Pixel wie folgt ändern.

Tyyppi_77
quelle
1
1. Ganz falscher Ansatz, berühren Sie keine Pixel auf Texturen, für die Oberflächen bestimmt sind. - 2. Verwenden Sie SDL_MapRGB, um Farben zu berechnen. Es ist nicht sicher anzunehmen, dass alles 32-Bit-RGBA ist. - 3. Verwenden Sie surface->BytesPerPixel, es ist nicht sicher anzunehmen, dass ... usw.
MickLH
Das Weitergeben von Oberflächen und das Speichern dieser im Speicher lohnt sich meiner Meinung nach nicht. Das Ändern von Texturen und / oder Oberflächen sollte selten durchgeführt werden, sodass das Übergeben von Pixeln an die GPU hier kein Deal-Breaker ist. Dies SDL_MapRGBist jedoch ein gültiger Punkt.
Tyyppi_77
-1

falsch - Sie benötigen die Details des "Oberflächen" -Formats aus der Textur - bevor Sie MapRGB blind verwenden können.

Um die Daten zu erhalten, fragen Sie die Textur ab, wie oben beschrieben.

MapRGB erwartet, dass das Oberflächen-> Format (in meinem Fall das Oberflächenformat ^ .format) übergeben wird. check (SDL-Syntax in den Header-Dateien)

Das Rendern der Textur ist die effizientere Methode für SDL2. Sie rendern im Allgemeinen stapelweise - aktualisieren Sie keine einzelnen Pixel - (zumindest nicht bis zur nächsten Bildschirmaktualisierung). Viele Leute rendern und realisieren es. Nicht präsentieren, bis der Bildschirm (der Monitor) dazu bereit ist - dies führt zu "Flimmern". Persönlich würde ich warten, bis alles gerendert ist, um fertig zu sein ... und dann die nächste Charge von Operationen vorbereiten.

JCoderJazzy
quelle