DrawPolyEx() bug & performance

edited October 2016 in raylib: shapes
I'm somewhat more confident that this one actually is a bug :P

DrawPolyEx leaves portions of some polygons unfilled, I think because of the way that it relies on just the vertices to fill in the polygon. If you run the example code below, you can see an example.

I get around this in my code using a custom poly struct that defines an origin, guaranteed to be inside, and defines the vertices as offsets from the origin. I then loop through and draw triangles with two of the vertices and the origin as the third vertex. So the center vector in the sample code below would actually be part of the struct and the offset vertices would be {50.0f, -150.0f}, etc if this was my real code. During update I move the anchor and then update an array of actual position vectors that I use for drawing using the new position of the anchor & the static offset data.

Also, I noticed that I get somewhat better performance using that method (see comments in the example code) - maybe because the DrawPolyEx code requires a bunch of array dereferencing operations that the DrawTriangle code doesn't?

Thanks as always for all your amazing work on this project!!!!

Sample code:


#include "raylib.h"

Vector2 vertices[6] =
{
{450.0f, 150.0f},
{400.0f, 50.0f},
{350.0f, 150.0f},
{350.0f, 450.0f},
{450.0f, 450.0f},
{450.0f, 150.0f}
};
int polys = 800;

void main(){
InitWindow(800, 600, "DrawPolyEx");
Vector2 center = (Vector2){GetScreenWidth()/2, GetScreenHeight()/2};

while(!WindowShouldClose()){
BeginDrawing();
ClearBackground(RAYWHITE);
DrawFPS(20, 20);

// 2300+ FPS with the outer loop commented out
for (int i=0; i<polys; i++){
// 2200+ FPS with neither

// about 140-142FPS with this method for the same 800 polys
DrawPolyEx(vertices, 6, RED);

// about 160-165FPS with this method for 800 6-vertex polys
/*
for (int j=0; j<5; j++){
DrawTriangle(vertices[j], vertices[j+1], center, RED);
}
*/
};

EndDrawing();
}

CloseWindow();

return 0;
}

Comments

  • Hi wly_cdgr!

    I see the problem, you're right, the function is not correctly implemented, it processes the triangles in the following way:

    1-2-3, 2-3-4, 3-4-5, 4-5-6

    image

    Finding a solution for this problem is not that easy if we want to keep the function simple and intuitive for the user...

    Possible solutions:

    1) Compute the centric point of the poly (given the vertices) and use it to draw the same way you proposed. The problem with this solution is the performance cost of computing the centric point every frame...

    2) Ask for a centric point (or at least inside poly) as a function parameter. User needs to provide that point... function usage could be not that confortable for the user...

    3) Rename function to DrawTriangleList() and process it like: 1-2-3, 4-5-6, 7-8-9,...


    Need to think about it... what do you think?


    The frames drop could be related to different things (usually related to drawing, that's always the most costly process):

    1) Internal buffers usage. Despite functions naming, DrawTriangle() uses QUADS buffer (internal array of vertices) to store drawing data, same as text, while DrawPolyEx() uses TRIANGLES buffer. So, if using DrawTriangle(), you only use (and process on drawing) one internal type of buffer (QUADS) while, when using DrawPoly() you force the use of two internal buffers (QUADS and TRIANGLES).

    2) Overdraw. Processing same screen pixels several times (the parts with more red color in the image) has a performance cost; keep in mind that a small program (shader) is executed in GPU to compute the final color of each pixel. This program perform a bunch of math operations for every pixel.

    3) Graphic driver. At the very end of drawing process, the graphics driver has the last word, it could take some obscure decisions trying to improve performance (independently of what program defines to do)...

  • edited October 2016
    In my game, bullets 'slice' polygons as they fly through them, and I just grab a point along the slice line and use it as the center point for both of the fragment polygons for drawing purposes. It at least ~looks~ like it works. So I wonder whether you mightn't be able to simply use the first vertex as the centric point? It works in the little testing that I've done.

    Although it wouldn't work for concave polygons like a bowtie. Hmm. It seems that you'd need an interior point that had a clear line of sight to all the vertices, unblocked by the boundaries. Or multiple points that taken together had a clearn LoS to all the vertices, and then you'd have to chop up the drawing.

    re: 1, ah! I hadn't considered which buffer the text functions are using.
    maybe I could draw the text with functions that use the LINES buffer to try and get a better reading :P...or just print the goshdang data to a console...
  • Hey wly_cdgr!

    Already corrected DrawPolyEx(), at least for convex polys; actually, it was easier than expected if we consider that all points are visible from the first one.

    It is corrected in GitHub develop branch (https://github.com/raysan5/raylib/blob/develop/src/shapes.c#L343), ready to be included in upcoming raylib 1.6.

    Now, you only need to provide the polygon points (5 in your example), no need for duplicates.

    About performance, now it seems to work at same framerate with DrawTriangles() and DrawPolyEx(), so, performance drop was possibly related to 2) Overdraw.

    Unfortunately, it's not possible to draw text using the LINES buffer... well, at least that you draw your own text characters line by line using DrawLine()... :P

  • hehe yeah that's what I meant about text, just drawing it with lines :P

    thanks for the fix! ~ looking forward to 1.6
Sign In or Register to comment.