SDL2: fast pixel manipulation

I want to draw pixels on the monitor, which often change after certain parameters. EG. if the red and green pixels collide, they disappear, etc.

In each frame, I have to manipulate about 100 - 1000 pixels. I have a multi-threaded approach that will not give me 30FPS (what I want). I am currently storing an array of pixels in RAM that contains all the pixels and has SDL_Surface . When a pixel in an array changes, it also changes on the surface and then after all the manipulations are completed, it becomes myopic to the screen. My current approach is too slow, and I thought a bit about how to increase speed.

My current thoughts are:

  • Use OpenGL to manipulate the pixels directly on the GPU, which some forums tell me is slower than my current approach, because "this is not how the GPU works."
  • Do not store an array of pixels, do not store BMP in RAM directly, do not manipulate it, and then move it to SDL_Surface or SDL_Texture

Are there any other approaches to how I can quickly manipulate pixels?

+7
c ++ image-processing sdl opengl sdl-2
source share
1 answer

SDL_CreateTexture() w / SDL_TEXTUREACCESS_STREAMING + SDL_UpdateTexture() seems to work quite well with the correct pixel format.

My system uses the default rendering tool:

 Renderer name: direct3d Texture formats: SDL_PIXELFORMAT_ARGB8888 SDL_PIXELFORMAT_YV12 SDL_PIXELFORMAT_IYUV 

(although opengl info is the same :)

 Renderer name: opengl Texture formats: SDL_PIXELFORMAT_ARGB8888 SDL_PIXELFORMAT_YV12 SDL_PIXELFORMAT_IYUV 

SDL_PIXELFORMAT_ARGB8888 gives me ~ 1 ms / frame:

 #include <SDL2/SDL.h> #include <SDL2/SDL_render.h> #include <iostream> #include <vector> using namespace std; int main( int argc, char** argv ) { SDL_Init( SDL_INIT_EVERYTHING ); atexit( SDL_Quit ); SDL_Window* window = SDL_CreateWindow ( "SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 600, 600, SDL_WINDOW_SHOWN ); SDL_Renderer* renderer = SDL_CreateRenderer ( window, -1, SDL_RENDERER_ACCELERATED ); SDL_RendererInfo info; SDL_GetRendererInfo( renderer, &info ); cout << "Renderer name: " << info.name << endl; cout << "Texture formats: " << endl; for( Uint32 i = 0; i < info.num_texture_formats; i++ ) { cout << SDL_GetPixelFormatName( info.texture_formats[i] ) << endl; } const unsigned int texWidth = 1024; const unsigned int texHeight = 1024; SDL_Texture* texture = SDL_CreateTexture ( renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, texWidth, texHeight ); vector< unsigned char > pixels( texWidth * texHeight * 4, 0 ); SDL_Event event; bool running = true; while( running ) { const Uint64 start = SDL_GetPerformanceCounter(); SDL_SetRenderDrawColor( renderer, 0, 0, 0, SDL_ALPHA_OPAQUE ); SDL_RenderClear( renderer ); while( SDL_PollEvent( &event ) ) { if( ( SDL_QUIT == event.type ) || ( SDL_KEYDOWN == event.type && SDL_SCANCODE_ESCAPE == event.key.keysym.scancode ) ) { running = false; break; } } // splat down some random pixels for( unsigned int i = 0; i < 1000; i++ ) { const unsigned int x = rand() % texWidth; const unsigned int y = rand() % texHeight; const unsigned int offset = ( texWidth * 4 * y ) + x * 4; pixels[ offset + 0 ] = rand() % 256; // b pixels[ offset + 1 ] = rand() % 256; // g pixels[ offset + 2 ] = rand() % 256; // r pixels[ offset + 3 ] = SDL_ALPHA_OPAQUE; // a } //unsigned char* lockedPixels; //int pitch; //SDL_LockTexture // ( // texture, // NULL, // reinterpret_cast< void** >( &lockedPixels ), // &pitch // ); //std::copy( pixels.begin(), pixels.end(), lockedPixels ); //SDL_UnlockTexture( texture ); SDL_UpdateTexture ( texture, NULL, &pixels[0], texWidth * 4 ); SDL_RenderCopy( renderer, texture, NULL, NULL ); SDL_RenderPresent( renderer ); const Uint64 end = SDL_GetPerformanceCounter(); const static Uint64 freq = SDL_GetPerformanceFrequency(); const double seconds = ( end - start ) / static_cast< double >( freq ); cout << "Frame time: " << seconds * 1000.0 << "ms" << endl; } SDL_DestroyRenderer( renderer ); SDL_DestroyWindow( window ); SDL_Quit(); } 

Make sure that you do not have vsync support (forcibly in the driver, starting the linker, etc.), otherwise all your frame times will be ~ 16 ms (or whatever you set on the display).

+6
source share

All Articles