本文介绍了SDL2:快速像素操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在显示器上绘制像素,在某些参数之后经常变化。例如。如果红色和绿色像素碰撞,它们都会消失等。

I want to draw pixels on the monitor which change frequently after certain parameters. E.G. if a Red and Green Pixel collide, they would both vanish, etc.

在每个帧中,我必须操纵大约100 - 1000像素。我有一个多线程的方法在这里,不会给我30FPS(我想要的)。目前,我在RAM中存储一个像素数组,其中包含所有像素,并有一个 SDL_Surface 。当数组中的一个像素发生变化时,它也会在Surface中被改变,然后在所有的操作完成之后,屏幕会被屏蔽掉。我目前的方法太慢了,我对如何提高速度有点想法。

In every frame I have to manipulate about 100 - 1000 pixels. I have a multi-threaded approach here, which wont give me 30FPS (what I want). Currently I store a Pixel array in the RAM which contains all Pixels and have a SDL_Surface. When a pixel in the array changes, it gets changed in the Surface too and is then after all manipulation is done gets blitted to the screen. My current approach is too slow and I did a bit of thinking on how I could increase the Speed.

我目前的想法是:


  • 使用OpenGL直接在GPU上进行像素操作,有些论坛告诉我,这比我目前的方法慢,因为这不是GPU的工作原理 / li>
  • 不要存储像素数组,直接将BMP存储在RAM中,操作它,然后将其移动到 SDL_Surface SDL_Texture

  • Use OpenGL to do the pixel manipulation directly on the GPU, which some forums tells me that this is way slower than my current approach as "this is not how a GPU works"
  • Don't store a pixel array, store a BMP in RAM directly, manipulate that and then move it to an SDL_Surface or SDL_Texture

有没有其他方法可以快速操作像素?

Are there any other approaches on how I could manipulate Pixels in a fast manner?

推荐答案

SDL_CreateTexture() w / SDL_TEXTUREACCESS_STREAMING + SDL_UpdateTexture()似乎能够以正确的像素格式工作。

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

在我使用默认渲染器的系统上:

On my system using the default renderer:

Renderer name: direct3d
Texture formats:
SDL_PIXELFORMAT_ARGB8888
SDL_PIXELFORMAT_YV12
SDL_PIXELFORMAT_IYUV

(尽管 opengl info是相同的:)

(though the opengl info is the same:)

Renderer name: opengl
Texture formats:
SDL_PIXELFORMAT_ARGB8888
SDL_PIXELFORMAT_YV12
SDL_PIXELFORMAT_IYUV

SDL_PIXELFORMAT_ARGB8888 给我〜1ms /帧:

SDL_PIXELFORMAT_ARGB8888 gives me ~1ms/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();
}

确保您没有启用vsync运行合成器等),否则 你的帧时间将是〜16ms(或任何你的显示刷新设置)。

Make sure you don't have have vsync enabled (forced in the driver, running a compositor, etc.) or else all your frame times will be ~16ms (or whatever your display refresh is set to).

这篇关于SDL2:快速像素操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-28 12:53
查看更多