Optimizing draw loop with SDL2_gfx polygons


#1

My game involves a tiled map, about 30 by 18, that the user can scroll around by moving the mouse to the edge of the screen. It performs very well just moving around normal terrain, it renders 600 boxes, 100 sprites, and a fancy gui without a problem. It begins lagging very badly when I move over a lake, however. A large lake draws about 100 polygons with 4 points to make the shore line.

I have a low end, on board, graphics chip, a Radeon HD 6290, but it seems like I should still be getting more shapes out of it. I also have a feeble processor, just 1 ghz, and this gets to 100% when the lag occurs, so I’m most concerned with optimizing from a CPU point of view.

The main loop, in pseudo-code, is something like this:

SDL_PollEvent
handle events
draw_tiles  // This is the function that takes up the most time in gprof, also where the lake drawing code is.
draw_gui
SDL_GL_SwapWindow(window); // I'm using the nanogui-SDL package, which, I assume, needs this call to draw
SDL_Delay(5); // To keep it from taking up 100% of the CPU

The renderer I use for everything is initialized like this:

SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

The drawing function is two for loops that go through the visible x and y tiles. WATERX_MEM and WATERY_MEM are two global arrays that serve as temporary storage, since the polygon drawing function wants an array. And here’s the code that actually draws it:

if (current_tile->has_water()) {
        WATERX_MEM[0] = current_tile->get_waterx()[0] + curx;
        WATERX_MEM[1] = current_tile->get_waterx()[1] + curx;
        WATERX_MEM[2] = current_tile->get_waterx()[2] + curx;
        WATERX_MEM[3] = current_tile->get_waterx()[3] + curx;

        WATERY_MEM[0] = current_tile->get_watery()[0] + cury;
        WATERY_MEM[1] = current_tile->get_watery()[1] + cury;
        WATERY_MEM[2] = current_tile->get_watery()[2] + cury;
        WATERY_MEM[3] = current_tile->get_watery()[3] + cury;

        filledPolygonRGBA (renderer,
                           WATERX_MEM,
                           WATERY_MEM,
                           4,
                           27, 25, 107, 255);

I’ve tried taking out the getter function and accessing the array directly. I’ve also tried replacing the filled polygon with a filled trigon that just used three of the points, and it lagged just as much. I appreciate any tips on how to do this more efficiently.


#2

My game involves a tiled map, about 30 by 18, that the user can scroll around by moving the mouse to the edge of the screen. It performs very well just moving around normal terrain, it renders 600 boxes, 100 sprites, and a fancy gui without a problem. It begins lagging very badly when I move over a lake, however. A large lake draws about 100 polygons with 4 points to make the shore line.

It appears SDL isn’t the right tool for this job, without jumping into the openGL. I’ve switched to SFML and a similar workload takes up about 1% of my CPU now.


#3

SFML add too many overhead if compare with direct OpenGL usage.
Better use batch drawing directly from OpenGL.

SDL here good because it do any initialization work, and allow draw anything in way what you want and can.


#4

This code looks not optimal. Can be many improvment.
For example call current_tile->get_waterx() only once. Also precalculate values for current_tile->get_waterx()[N] + curx.
If your video card too slow, probably enable software renderer with flag SDL_RENDERER_SOFTWARE.