Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Drawing filled polygons using the Surface API

11 views
Skip to first unread message

Guillermo Rodriguez Garcia

unread,
Jan 15, 2024, 7:14:21 PM1/15/24
to PlayN
Hi all,

The Surface API has methods to draw lines, so one can draw the outline of any polygon more or less easily, or even arcs and circles (by drawing an appropriate number of straight line segments). It also has a method to draw a filled rectangle. However, how can you draw a filled shape other than a rectangle? for example a triangle, or a trapezoid (in my case I need to draw a number of trapezoids).

(I know I can do this offscreen using the Canvas API and then generate a texture from the canvas.)

Best regards,

Guillermo

Michael Bayne

unread,
Jan 15, 2024, 7:40:56 PM1/15/24
to pl...@googlegroups.com
PlayN doesn't have a good API for drawing arbitrary polygons via accelerated GPU commands. It is possible, but you have to use the TriangleBatch API and convert your polygon to triangles yourself.

PlayN is optimized for rendering sprites (aka quads), so its whole rendering pipeline is mainly organized around that. The Surface API provides a thin layer over the Textured/QuadBatch API, which just draws a bunch of textured quads to the screen.

There are two implementations of QuadBatch: UniformQuadBatch, which PlayN tries to use by default, because it can draw textured quads by sending less data to the GPU, or TriangleBatch which just draws two triangles for each quad. But TriangleBatch also allows you to just send your own triangulated mesh.

Writing general purpose code for triangulating polygons is hard to do because you probably don't want to do this every time you render the polygon, so it would not make sense to have a Surface API that took some sort of polygon description and then did the expensive and memory wasteful process of converting that to triangles, only to throw it all away and do it again on the next frame.

We'd probably want some sort of object which was used to define the polygon by adding points, and then which maintained an internal cached triangulation, which could be computed once (and invalidated if the polygon was changed) and then Surface could expose an API to draw those. And we'd have to document that if you want to use that API you have to force PlayN to use the TriangleBatch instead of the QuadBatch (because the batch dictates the shader that's being used to draw the Surface, and the way PlayN is architected, we can't change shaders in the middle of rendering).

So it's a little messy and special casey. But it is pretty useful, so maybe it would be worth the rough edges.


--

---
You received this message because you are subscribed to the Google Groups "PlayN" group.
To unsubscribe from this group and stop receiving emails from it, send an email to playn+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/playn/47995236-a97d-4b46-9b5d-6034d0c71755n%40googlegroups.com.


--

Michael Bayne

unread,
Jan 15, 2024, 7:45:38 PM1/15/24
to pl...@googlegroups.com
I glossed over that you said you just need to draw trapezoids. In that case, it's probably pretty easy to represent them directly as a triangle mesh, and then you can just add them to the drawing batch directly. So you'd override createDefaultBatch in your SceneGame subclass (assuming you're using one), and always create a TriangleBatch, and then when you want to render your trapezoids, just add then to the SceneGame.defaultBatch directly.

You could also create a separate TriangleBatch and use Surface.pushBatch/popBatch to switch to that batch while rendering, but that will flush all of your other pending drawing commands to the GPU, _just_ draw the trapezoids, and then flush those drawing commands to the GPU before resuming your other rendering. Which might be fine, but if you always use TriangleBatch then your trapezoids can be part of your main rendering batch.

--

Guillermo Rodriguez Garcia

unread,
Jan 15, 2024, 8:25:52 PM1/15/24
to PlayN
I see. For my specific use case I will probably end up using Canvas since the trapezoids are "mostly static" (not really static but they do not change from frame to frame). But my first approach was to check the Surface API, then I found that you can basically draw any polygon outline, but only filled rectangles, and wanted to check if I was missing something

Re. pushBath/popBatch and the flushing, I had a quick look at libgdx's ShapeRenderer and found an almost identical warning :-) "One of the downsides of using a ShapeRenderer is that it uses its own Mesh, meaning if you want to alternate between ShapeRenderer and a Batch you need to start and end (and flush) each one before switching, which can significantly drop performance." [1]

Then it mentions a "ShapeDrawer" 3rd party library as an alternative: "An alternative is to use the third party library ShapeDrawer, which uses a user-provided Batch to draw shapes. It has most of the functionality of ShapeRenderer, plus some extras like line joining/bevelling. It also doesn’t draw over itself when drawing shapes so it can be used with transparent colours, and doesn’t need to be flushed when switching from drawing lines to filled shapes". The ShapeDrawer [2] library seems fairly complex.


Best regards,

Guillermo
Reply all
Reply to author
Forward
0 new messages