2015-10-23 15 views
7

あるパラメータの後に頻繁に変化するピクセルをモニタに描画したい。例えば。赤と緑のピクセルが衝突すると、それらは消滅します。SDL2:高速ピクセル操作

すべてのフレームで、約100〜1000ピクセルを操作する必要があります。私はここでマルチスレッドのアプローチをしていますが、私は30FPS(私が望むもの)を与えません。現在、すべてのピクセルを含むRAMにピクセル配列を格納し、SDL_Surfaceを持っています。配列内のピクセルが変化すると、サーフェスでも変化し、すべての操作が完了した後で画面にblitされます。私の現在のアプローチは遅すぎるので、私はスピードをどのように高めることができるかについて少し考えました。

私の現在の考えは以下のとおりです。

  • 使用OpenGLのいくつかのフォーラムが、これはどのようにGPUの動作ではありません」と、これは私の現在のアプローチよりも道遅いことを私に語ったGPU上で直接ピクセル操作を行うには「
  • は、私は、高速のピクセルを操作することができる方法上の任意の他のアプローチがありますが、直接RAMにBMPを格納し、画素アレイを保存することを操作して、SDL_SurfaceまたはSDL_Texture

にそれを移動しないでください方法?

+3

私は、ピクセル操作自体が低いFPSの原因ではないと思います。スクリーン上のピクセルをランダムに変更した場合(1Kだけではありません)、30FPSを上回るようにしてください。 [Here](http://stackoverflow.com/a/24170211/833188)は、パフォーマンスのために 'SDL_Texture'を使うべきだと言っています。あなたはそれを試しましたか?とにかくコードをプロファイリングしましたか? – Sga

+0

私は 'TEXTURE_STREAMING'を持つ' SDL_Texture'を持っています。テクスチャをロックし、得られたピクセル配列の操作を行い、終了するとロックを解除します。 – Nidhoegger

+0

プロファイリングだけがボトルネックがどこにあるのかを知ることができます – Sga

答えて

6

w/SDL_TEXTUREACCESS_STREAMING + SDL_UpdateTexture()は、適切なピクセル形式で十分に機能するようです。デフォルトのレンダリング使用して、私のシステムでは

Renderer name: direct3d 
Texture formats: 
SDL_PIXELFORMAT_ARGB8888 
SDL_PIXELFORMAT_YV12 
SDL_PIXELFORMAT_IYUV 

opengl情報が同じ:)

Renderer name: opengl 
Texture formats: 
SDL_PIXELFORMAT_ARGB8888 
SDL_PIXELFORMAT_YV12 
SDL_PIXELFORMAT_IYUV 

SDL_PIXELFORMAT_ARGB8888ですが、私を与えるを〜1msの/フレーム:

#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(); 
} 

vsyncを有効にしていないことを確認してください(ドライバを強制し、coディスプレイのリフレッシュが何に設定されていてもフレーム時間は〜16msになります。

+1

ありがとうございました! – Nidhoegger

+0

あなたはどのシステムを使用しているのか聞いてもよろしいですか?ここでi5のIntel HD 2000でi7 2600kでフレームあたり約10msをGTX 560で取得すると3msが得られます。どちらもgentoo Linuxを動かしています。どうも! – Nidhoegger

+0

@Nidhoegger:i7 2600 @ 3.4GHz、AMD FirePro V4800を搭載したWin7。 – genpfault

関連する問題